blocks = getChildren();
+
+ // Remove old child
+ blocks.remove(position);
+ oldBlock.setParent(null);
+
+ // Insert new children
+ Block previousBlock = oldBlock.getPreviousSibling();
+ if (newBlocks.isEmpty()) {
+ previousBlock.setNextSiblingBlock(oldBlock.getNextSibling());
+ }
+ Block lastBlock = null;
+ for (Block block : newBlocks) {
+ block.setParent(this);
+ block.setPreviousSiblingBlock(previousBlock);
+ if (previousBlock != null) {
+ previousBlock.setNextSiblingBlock(block);
+ }
+ previousBlock = block;
+ lastBlock = block;
+ }
+ Block nextBlock = oldBlock.getNextSibling();
+ if (nextBlock != null) {
+ nextBlock.setPreviousSiblingBlock(lastBlock);
+ }
+ if (lastBlock != null) {
+ lastBlock.setNextSiblingBlock(nextBlock);
+ }
+
+ blocks.addAll(position, newBlocks);
+
+ oldBlock.setNextSiblingBlock(null);
+ oldBlock.setPreviousSiblingBlock(null);
+ }
+
+ /**
+ * Get the position of the provided block in the list of children.
+ *
+ * Can't use {@link List#indexOf(Object)} since it's using {@link Object#equals(Object)}
+ * internally which is not
+ * what we want since two WordBlock with the same text or two spaces are equals for example but we
+ * want to be able
+ * to target one specific Block.
+ *
+ * @param block
+ * the block
+ * @return the position of the block, -1 if the block can't be found
+ */
+ private int indexOfChild(Block block) {
+ return indexOfBlock(block, getChildren());
+ }
+
+ /**
+ * Get the position of the provided block in the provided list of blocks.
+ *
+ * Can't use {@link List#indexOf(Object)} since it's using {@link Object#equals(Object)}
+ * internally which is not
+ * what we want since two WordBlock with the same text or two spaces are equals for example but we
+ * want to be able
+ * to target one specific Block.
+ *
+ * @param block
+ * the block for which to find the position
+ * @param blocks
+ * the list of blocks in which to look for the passed block
+ * @return the position of the block, -1 if the block can't be found
+ */
+ private int indexOfBlock(Block block, List blocks) {
+ int position = 0;
+
+ for (Block child : blocks) {
+ if (child == block) {
+ return position;
+ }
+ ++position;
+ }
+
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#getChildren()
+ */
+ public List getChildren() {
+ return this.childrenBlocks;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#getParent()
+ */
+ public Block getParent() {
+ return this.parentBlock;
+ }
+
+ /**
+ * @return all parameters
+ */
+ public Map getParameters() {
+ return Collections.unmodifiableMap(this.parameters);
+ }
+
+ /**
+ * A Parameter is a generic key/value which can be used to add metadata to a block. What is done
+ * with the metadata
+ * depends on the Renderer's implementations. For example the XHTML Renderer adds them as Element
+ * attributes.
+ *
+ * @param name
+ * the name of the parameter to return
+ * @return the parameter or null if the parameter doesn't exist
+ */
+ public String getParameter(String name) {
+ return this.parameters.get(name);
+ }
+
+ /**
+ * Set a parameter on the current block. See {@link #getParameter(String)} for more details.
+ *
+ * @param name
+ * the parameter's name
+ * @param value
+ * the parameter's value
+ */
+ public void setParameter(String name, String value) {
+ this.parameters.put(name, value);
+ }
+
+ /**
+ * Set several parameters at once.
+ *
+ * @param parameters
+ * the parameters to set
+ * @see #getParameter(String)
+ * @since 1.7M2
+ */
+ public void setParameters(Map parameters) {
+ this.parameters.putAll(parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#setParent(org.xwiki.rendering.block.Block)
+ */
+ public void setParent(Block parentBlock) {
+ this.parentBlock = parentBlock;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#getRoot()
+ */
+ public Block getRoot() {
+ Block block = this;
+
+ while (block.getParent() != null) {
+ block = block.getParent();
+ }
+
+ return block;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#getChildrenByType(java.lang.Class, boolean)
+ */
+ public List getChildrenByType(Class blockClass, boolean recurse) {
+ List typedBlocks = new ArrayList();
+ for (Block block : getChildren()) {
+ if (blockClass.isAssignableFrom(block.getClass())) {
+ typedBlocks.add(blockClass.cast(block));
+ }
+ if (recurse && !block.getChildren().isEmpty()) {
+ typedBlocks.addAll(block.getChildrenByType(blockClass, true));
+ }
+ }
+
+ return typedBlocks;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#getPreviousBlockByType(java.lang.Class, boolean)
+ */
+ public T getPreviousBlockByType(Class blockClass, boolean recurse) {
+ if (getParent() == null) {
+ return null;
+ }
+
+ int index = indexOfBlock(this, getParent().getChildren());
+
+ // test previous brothers
+ List blocks = getParent().getChildren();
+ for (int i = index - 1; i >= 0; --i) {
+ Block previousBlock = blocks.get(i);
+ if (blockClass.isAssignableFrom(previousBlock.getClass())) {
+ return blockClass.cast(previousBlock);
+ }
+ }
+
+ // test parent
+ if (blockClass.isAssignableFrom(getParent().getClass())) {
+ return blockClass.cast(getParent());
+ }
+
+ // recurse
+ return recurse ? getParent().getPreviousBlockByType(blockClass, true) : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#getParentBlockByType(java.lang.Class)
+ */
+ public T getParentBlockByType(Class blockClass) {
+ Block parent = getParent();
+
+ if (parent == null || blockClass.isAssignableFrom(parent.getClass())) {
+ return blockClass.cast(parent);
+ }
+
+ return parent.getParentBlockByType(blockClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Block#getNextSibling()
+ * @since 2.6RC1
+ */
+ public Block getNextSibling() {
+ return this.nextSiblingBlock;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Block#getPreviousSibling()
+ * @since 2.6RC1
+ */
+ public Block getPreviousSibling() {
+ return this.previousSiblingBlock;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#removeBlock(Block)
+ * @since 2.6RC1
+ */
+ public void removeBlock(Block childBlockToRemove) {
+ getChildren().remove(childBlockToRemove);
+ if (childBlockToRemove != null) {
+ Block previousBlock = childBlockToRemove.getPreviousSibling();
+ if (previousBlock != null) {
+ previousBlock.setNextSiblingBlock(childBlockToRemove.getNextSibling());
+ }
+ Block nextBlock = childBlockToRemove.getNextSibling();
+ if (nextBlock != null) {
+ nextBlock.setPreviousSiblingBlock(previousBlock);
+ }
+ childBlockToRemove.setNextSiblingBlock(null);
+ childBlockToRemove.setPreviousSiblingBlock(null);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see EqualsBuilder#reflectionEquals(Object, Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return EqualsBuilder.reflectionEquals(this, obj);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see HashCodeBuilder#reflectionHashCode(Object)
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeBuilder.reflectionHashCode(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#clone()
+ */
+ @Override
+ public Block clone() {
+ return clone(null);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#clone(org.xwiki.rendering.block.BlockFilter)
+ * @since 1.8RC2
+ */
+ public Block clone(BlockFilter blockFilter) {
+ Block block;
+ try {
+ block = (AbstractBlock) super.clone();
+ } catch (CloneNotSupportedException e) {
+ // Should never happen
+ throw new RuntimeException("Failed to clone object", e);
+ }
+
+ ((AbstractBlock) block).parameters = new LinkedHashMap(this.parameters);
+
+ ((AbstractBlock) block).childrenBlocks = new ArrayList(this.childrenBlocks.size());
+ for (Block childBlock : this.childrenBlocks) {
+ if (blockFilter != null) {
+ Block clonedChildBlocks = childBlock.clone(blockFilter);
+
+ List filteredBlocks = blockFilter.filter(clonedChildBlocks);
+
+ if (filteredBlocks.size() == 0) {
+ filteredBlocks = clonedChildBlocks.getChildren();
+ }
+
+ block.addChildren(filteredBlocks);
+ } else {
+ block.addChild(childBlock.clone());
+ }
+ }
+
+ return block;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractFatherBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractFatherBlock.java
new file mode 100644
index 000000000..6d37344c6
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractFatherBlock.java
@@ -0,0 +1,73 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Default implementation for {@link FatherBlock}.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public abstract class AbstractFatherBlock extends AbstractBlock implements FatherBlock {
+
+ /**
+ * Constructs a block with children blocks.
+ *
+ * @param childrenBlocks
+ * the list of children blocks of the block to construct
+ */
+ public AbstractFatherBlock(List childrenBlocks) {
+ this(childrenBlocks, Collections.emptyMap());
+ }
+
+ /**
+ * Construct a block with children blocks and parameters.
+ *
+ * @param childrenBlocks
+ * the list of children blocks of the block to construct
+ * @param parameters
+ * the parameters to set
+ */
+ public AbstractFatherBlock(List childrenBlocks, Map parameters) {
+ super(parameters);
+ addChildren(childrenBlocks);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ before(listener);
+
+ for (Block block : getChildren()) {
+ block.traverse(listener);
+ }
+
+ after(listener);
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/Block.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/Block.java
new file mode 100644
index 000000000..9b61cf9d6
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/Block.java
@@ -0,0 +1,249 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents an element of a XWiki Document's content. For example there are Blocks for Paragraphs,
+ * Bold parts,
+ * Sections, Links, etc. A block has a parent and can have children too for Blocks which are wrapper
+ * around other blocks
+ * (e.g. Paragraph blocks, List blocks, Bold blocks).
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public interface Block extends Cloneable {
+
+ /**
+ * Let the block send {@link Listener} events corresponding to its content. For example a
+ * Paragraph block will send
+ * the {@link org.xwiki.rendering.listener.Listener#beginParagraph} and
+ * {@link org.xwiki.rendering.listener.Listener#endParagraph} events when this method is called.
+ *
+ * @param listener
+ * the listener to which to send the events to.
+ */
+ void traverse(Listener listener);
+
+ /**
+ * Helper method to add a single child block to the end of the children list of the current block.
+ * For adding
+ * several blocks at once use {@link #addChildren(java.util.List)}.
+ *
+ * @param blockToAdd
+ * the child block to add
+ */
+ void addChild(Block blockToAdd);
+
+ /**
+ * Adds several children blocks to the end of the children list of the current block. For example
+ * a bold sentence is
+ * made up of a Bold block to which the different words making up the text have been added to.
+ *
+ * @param blocksToAdd
+ * the children blocks to add
+ */
+ void addChildren(List extends Block> blocksToAdd);
+
+ /**
+ * Helper method to add a single child block to the current block before the provided existing
+ * child block. For
+ * adding several blocks at once use {@link #addChildren(java.util.List)}.
+ *
+ * @param blockToInsert
+ * the child block to add
+ * @param nextBlock
+ * the child block that will be just after the added block
+ * @since 1.6M1
+ */
+ void insertChildBefore(Block blockToInsert, Block nextBlock);
+
+ /**
+ * Helper method to add a single child block to the current block after the provided existing
+ * child block. For
+ * adding several blocks at once use {@link #addChildren(java.util.List)}.
+ *
+ * @param blockToInsert
+ * the child block to add
+ * @param previousBlock
+ * the child block that will be just before the added block
+ * @since 1.6M1
+ */
+ void insertChildAfter(Block blockToInsert, Block previousBlock);
+
+ /**
+ * Replaces an existing children block with the passed new block. Also sets the new block's parent
+ * to be the current
+ * block.
+ *
+ * @param newBlock
+ * the new block to replace the old block with
+ * @param oldBlock
+ * the block to replace with the new block
+ */
+ void replaceChild(Block newBlock, Block oldBlock);
+
+ /**
+ * Replaces an existing children block with the passed new blocks. Also sets the new block's
+ * parents to be the
+ * current block.
+ *
+ * @param newBlocks
+ * the new blocks to replace the old block with
+ * @param oldBlock
+ * the block to replace with the new blocks
+ */
+ void replaceChild(List newBlocks, Block oldBlock);
+
+ /**
+ * Get the parent block. All blocks have a parent and the top level parent is the {@link XDOM}
+ * object.
+ *
+ * @return the parent block
+ */
+ Block getParent();
+
+ /**
+ * Sets the parent block.
+ *
+ * @param parentBlock
+ * the parent block
+ */
+ void setParent(Block parentBlock);
+
+ /**
+ * Gets all children blocks.
+ *
+ * @return the children blocks
+ * @see #addChildren(java.util.List)
+ */
+ List getChildren();
+
+ /**
+ * Gets the top level Block. If the current block is the top level Block, it return itself.
+ *
+ * @return the top level Block
+ */
+ Block getRoot();
+
+ /**
+ * Gets all the Blocks in the tree which are of the passed Block class.
+ *
+ * @param
+ * the class of the Blocks to return
+ * @param blockClass
+ * the block class to look for
+ * @param recurse
+ * if true also search recursively children
+ * @return all the matching blocks
+ * @since 1.6M1
+ */
+ List getChildrenByType(Class blockClass, boolean recurse);
+
+ /**
+ * Look upward to find a block which inherit or is provided type.
+ *
+ * The difference with {@link #getParentBlockByType(Class)} is that this one look also at previous
+ * block in the same
+ * parent when {@link #getParentBlockByType(Class)} only look at parents.
+ *
+ * @param
+ * the class of the Blocks to return
+ * @param blockClass
+ * the block class to look for
+ * @param recurse
+ * if true also search in parents levels
+ * @return the found block, null if nothing is found
+ * @since 1.6M1
+ */
+ T getPreviousBlockByType(Class blockClass, boolean recurse);
+
+ /**
+ * Recursively look at parents to find a block which inherits or is provided type.
+ *
+ * The difference with {@link #getPreviousBlockByType(Class, boolean)} is that this one only look
+ * at parent when
+ * {@link #getPreviousBlockByType(Class, boolean)} look at previous block in the same parent.
+ *
+ * @param
+ * the class of the Blocks to return
+ * @param blockClass
+ * the block class to look for
+ * @return the found block, null if nothing is found
+ * @since 1.9.1
+ */
+ T getParentBlockByType(Class blockClass);
+
+ /**
+ * Removes a Block.
+ *
+ * @param childBlockToRemove
+ * the child block to remove
+ * @since 2.6RC1
+ */
+ void removeBlock(Block childBlockToRemove);
+
+ /**
+ * @return the next sibling block or null if there's no next sibling
+ * @since 2.6RC1
+ */
+ Block getNextSibling();
+
+ /**
+ * @param nextSiblingBlock
+ * see {@link #getNextSibling()}
+ * @since 2.6RC1
+ */
+ void setNextSiblingBlock(Block nextSiblingBlock);
+
+ /**
+ * @return the previous sibling block or null if there's no previous sibling
+ * @since 2.6RC1
+ */
+ Block getPreviousSibling();
+
+ /**
+ * @param previousSiblingBlock
+ * see {@link #getPreviousSibling()} ()}
+ * @since 2.6RC1
+ */
+ void setPreviousSiblingBlock(Block previousSiblingBlock);
+
+ /**
+ * Return a copy of the block with filtered children.
+ *
+ * @param blockFilter
+ * the Block filter.
+ * @return the filtered Block.
+ * @since 1.8RC2
+ */
+ Block clone(BlockFilter blockFilter);
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Object#clone()
+ */
+ Block clone();
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BlockFilter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BlockFilter.java
new file mode 100644
index 000000000..73289c4e0
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BlockFilter.java
@@ -0,0 +1,50 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+
+/**
+ * Filter provided block into one or more block.
+ *
+ * The block filter is generally called for each block in a block list and is asked to return a
+ * filtered version of the
+ * provided block. This means:
+ *
+ * - an empty list if the block as to be removed
+ * - the block itself in a list if the filter does not have anything particular to filter on
+ * it
+ * - or even a list of new block to replace the provided block
+ *
+ *
+ * @version $Id$
+ * @since 1.8RC2
+ */
+public interface BlockFilter {
+
+ /**
+ * Filter provided block into zero or more block.
+ *
+ * @param block
+ * the block to filter.
+ * @return should never be null. The filtered blocks or empty list.
+ */
+ List filter(Block block);
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BulletedListBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BulletedListBlock.java
new file mode 100644
index 000000000..317cca90d
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BulletedListBlock.java
@@ -0,0 +1,77 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.ListType;
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a Bulleted list.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class BulletedListBlock extends AbstractFatherBlock implements ListBLock {
+
+ /**
+ * Construct a Bulleted List Block with no parameters.
+ *
+ * @param childrenBlocks
+ * the blocks making the list
+ */
+ public BulletedListBlock(List childrenBlocks) {
+ super(childrenBlocks);
+ }
+
+ /**
+ * Construct a Bulleted List Block with parameters.
+ *
+ * @param childrenBlocks
+ * the blocks making the list
+ * @param parameters
+ * see {@link org.xwiki.rendering.block.AbstractBlock#getParameter(String)} for more
+ * details on
+ * parameters
+ */
+ public BulletedListBlock(List childrenBlocks, Map parameters) {
+ super(childrenBlocks, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginList(ListType.BULLETED, getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endList(ListType.BULLETED, getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionDescriptionBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionDescriptionBlock.java
new file mode 100644
index 000000000..9ad3be305
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionDescriptionBlock.java
@@ -0,0 +1,61 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+import java.util.List;
+
+/**
+ * Represents a definition description. For exampe in HTML this is the equivalent of <dd>.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class DefinitionDescriptionBlock extends AbstractFatherBlock {
+
+ /**
+ * Construct a Definition Description block.
+ *
+ * @param childrenBlocks
+ * the blocks making the description
+ */
+ public DefinitionDescriptionBlock(List childrenBlocks) {
+ super(childrenBlocks);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginDefinitionDescription();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endDefinitionDescription();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionListBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionListBlock.java
new file mode 100644
index 000000000..1f629c8df
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionListBlock.java
@@ -0,0 +1,76 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents a definition list. For example in HTML this is the equivalent of <dl>.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class DefinitionListBlock extends AbstractFatherBlock implements ListBLock {
+
+ /**
+ * Construct a Definition List block with no parameters.
+ *
+ * @param childrenBlocks
+ * the blocks making the Definition list
+ */
+ public DefinitionListBlock(List childrenBlocks) {
+ super(childrenBlocks);
+ }
+
+ /**
+ * Construct a Definition List Block with parameters.
+ *
+ * @param childrenBlocks
+ * the blocks making the Definition list
+ * @param parameters
+ * see {@link org.xwiki.rendering.block.AbstractBlock#getParameter(String)} for more
+ * details on
+ * parameters
+ */
+ public DefinitionListBlock(List childrenBlocks, Map parameters) {
+ super(childrenBlocks, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginDefinitionList(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endDefinitionList(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionTermBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionTermBlock.java
new file mode 100644
index 000000000..878cd228e
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionTermBlock.java
@@ -0,0 +1,61 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+import java.util.List;
+
+/**
+ * Represents a definition description. For exampe in HTML this is the equivalent of <dt>.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class DefinitionTermBlock extends AbstractFatherBlock {
+
+ /**
+ * Construct a Definition Term block.
+ *
+ * @param childrenBlocks
+ * the blocks making the Definition Term
+ */
+ public DefinitionTermBlock(List childrenBlocks) {
+ super(childrenBlocks);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginDefinitionTerm();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endDefinitionTerm();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/EmptyLinesBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/EmptyLinesBlock.java
new file mode 100644
index 000000000..c2adedc9e
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/EmptyLinesBlock.java
@@ -0,0 +1,70 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents an empty line between 2 standalone Blocks. A standalone block is block that is not
+ * included in another
+ * block. Standalone blocks are Paragraph, Standalone Macro, Lists, Table, etc.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class EmptyLinesBlock extends AbstractBlock {
+
+ /**
+ * Number of empty lines between 2 standalone Blocks.
+ */
+ private int count;
+
+ /**
+ * @param count
+ * the number of empty lines between 2 standalone Blocks
+ */
+ public EmptyLinesBlock(int count) {
+ setEmptyLinesCount(count);
+ }
+
+ /**
+ * @return the number of empty lines between 2 standalone Blocks
+ */
+ public int getEmptyLinesCount() {
+ return this.count;
+ }
+
+ /**
+ * @param count
+ * the number of empty lines between 2 standalone Blocks
+ */
+ public void setEmptyLinesCount(int count) {
+ this.count = count;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractBlock#traverse(Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onEmptyLines(getEmptyLinesCount());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FatherBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FatherBlock.java
new file mode 100644
index 000000000..a7335ac17
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FatherBlock.java
@@ -0,0 +1,58 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * A type of {@link Block} that has children Blocks. For example the Paragraph Block, the Bold
+ * Block, the List Block,
+ * etc.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public interface FatherBlock extends Block {
+
+ /**
+ * Send {@link org.xwiki.rendering.listener.Listener} events corresponding to the start of the
+ * father block. For
+ * example for a Bold block, this allows an XHTML Listener (aka a Renderer) to output
+ * <b>.
+ *
+ * @param listener
+ * the listener that will receive the events sent by the father block before the children
+ * blocks have
+ * emitted their own events.
+ */
+ void before(Listener listener);
+
+ /**
+ * Send {@link Listener} events corresponding to the end of the father block. For example for a
+ * Bold block, this
+ * allows an XHTML Listener (aka a Renderer) to output </b>.
+ *
+ * @param listener
+ * the listener that will receive the events sent by the father block after the children
+ * blocks have
+ * emitted their own events.
+ */
+ void after(Listener listener);
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FormatBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FormatBlock.java
new file mode 100644
index 000000000..b4552667c
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FormatBlock.java
@@ -0,0 +1,89 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Format;
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a text formatting block (bold, italic, etc).
+ *
+ * @version $Id$
+ * @since 1.6M1
+ */
+public class FormatBlock extends AbstractFatherBlock {
+
+ /**
+ * The formatting to apply to the children blocks.
+ */
+ private Format format;
+
+ /**
+ * @param childrenBlocks
+ * the nested children blocks
+ * @param format
+ * the formatting to apply to the children blocks
+ */
+ public FormatBlock(List childrenBlocks, Format format) {
+ this(childrenBlocks, format, Collections.emptyMap());
+ }
+
+ /**
+ * @param childrenBlocks
+ * the nested children blocks
+ * @param format
+ * the formatting to apply to the children blocks
+ * @param parameters
+ * the custom parameters
+ */
+ public FormatBlock(List childrenBlocks, Format format, Map parameters) {
+ super(childrenBlocks, parameters);
+ this.format = format;
+ }
+
+ /**
+ * @return the formatting to apply to the children blocks
+ */
+ public Format getFormat() {
+ return this.format;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginFormat(getFormat(), getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endFormat(getFormat(), getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/GroupBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/GroupBlock.java
new file mode 100644
index 000000000..0e1a1b7ee
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/GroupBlock.java
@@ -0,0 +1,92 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a grouping of blocks.
+ *
+ * @version $Id$
+ * @since 1.8.3
+ */
+public class GroupBlock extends AbstractFatherBlock {
+
+ /**
+ * Create an empty group block with no children. This is useful when the user wants to call
+ * {@link #addChild(Block)}
+ * manually for adding children one by one after the block is constructed.
+ */
+ public GroupBlock() {
+ this(Collections.emptyList());
+ }
+
+ /**
+ * Create an empty group block with no children. This is useful when the user wants to call
+ * {@link #addChild(Block)}
+ * manually for adding children one by one after the block is constructed.
+ *
+ * @param parameters
+ * the parameters of the group
+ */
+ public GroupBlock(Map parameters) {
+ this(Collections.emptyList(), parameters);
+ }
+
+ /**
+ * @param blocks
+ * the children blocks of the group
+ */
+ public GroupBlock(List blocks) {
+ super(blocks);
+ }
+
+ /**
+ * @param blocks
+ * the children blocks of the group
+ * @param parameters
+ * the parameters of the group
+ */
+ public GroupBlock(List blocks, Map parameters) {
+ super(blocks, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginGroup(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endGroup(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HeaderBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HeaderBlock.java
new file mode 100644
index 000000000..a4f73b667
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HeaderBlock.java
@@ -0,0 +1,138 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+import org.xwiki.rendering.listener.HeaderLevel;
+
+/**
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class HeaderBlock extends AbstractFatherBlock {
+
+ /**
+ * The level of the header.
+ */
+ private HeaderLevel level;
+
+ /**
+ * The id of the header.
+ */
+ private String id;
+
+ /**
+ * @param childBlocks
+ * the children of the header.
+ * @param level
+ * the level of the header
+ */
+ public HeaderBlock(List childBlocks, HeaderLevel level) {
+ super(childBlocks);
+
+ this.level = level;
+ }
+
+ /**
+ * @param childBlocks
+ * the children of the header.
+ * @param level
+ * the level of the header
+ * @param parameters
+ * the parameters of the header
+ */
+ public HeaderBlock(List childBlocks, HeaderLevel level, Map parameters) {
+ super(childBlocks, parameters);
+
+ this.level = level;
+ }
+
+ /**
+ * @param childBlocks
+ * the children of the header.
+ * @param level
+ * the level of the header
+ * @param id
+ * the id of the header.
+ */
+ public HeaderBlock(List childBlocks, HeaderLevel level, String id) {
+ this(childBlocks, level);
+
+ this.id = id;
+ }
+
+ /**
+ * @param childBlocks
+ * the children of the header.
+ * @param level
+ * the level of the header
+ * @param parameters
+ * the parameters of the header
+ * @param id
+ * the id of the header.
+ */
+ public HeaderBlock(List childBlocks, HeaderLevel level, Map parameters, String id) {
+ this(childBlocks, level, parameters);
+
+ this.id = id;
+ }
+
+ /**
+ * @return the level of the header
+ */
+ public HeaderLevel getLevel() {
+ return this.level;
+ }
+
+ /**
+ * @return the id of the header.
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * @return the {@link SectionBlock} corresponding to this header
+ */
+ public SectionBlock getSection() {
+ return (SectionBlock) getParent();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginHeader(getLevel(), getId(), getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endHeader(getLevel(), getId(), getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HorizontalLineBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HorizontalLineBlock.java
new file mode 100644
index 000000000..a71e8004a
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HorizontalLineBlock.java
@@ -0,0 +1,61 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a Horizontal line.
+ *
+ * @version $Id$
+ * @since 1.6M1
+ */
+public class HorizontalLineBlock extends AbstractBlock {
+
+ /**
+ * Construct a Horizontal Line Block with no parameters.
+ */
+ public HorizontalLineBlock() {
+ super();
+ }
+
+ /**
+ * Construct a Horizontal Line Block with parameters.
+ *
+ * @param parameters
+ * see {@link org.xwiki.rendering.block.AbstractBlock#getParameter(String)} for more
+ * details on
+ * parameters
+ */
+ public HorizontalLineBlock(Map parameters) {
+ super(parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onHorizontalLine(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/IdBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/IdBlock.java
new file mode 100644
index 000000000..11a11d766
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/IdBlock.java
@@ -0,0 +1,63 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * A reference/location in a page. In HTML for example this is called an Anchor. It allows pointing
+ * to that location,
+ * for example in links.
+ *
+ * @version $Id$
+ * @since 1.6M1
+ * @see Listener#onId(String)
+ */
+public class IdBlock extends AbstractBlock {
+
+ /**
+ * The unique name for the reference/location.
+ */
+ private String name;
+
+ /**
+ * @param name
+ * the unique name for the reference/location.
+ */
+ public IdBlock(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the reference/location name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onId(getName());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ImageBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ImageBlock.java
new file mode 100644
index 000000000..59f9eac2b
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ImageBlock.java
@@ -0,0 +1,115 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+
+/**
+ * Represents an image.
+ *
+ * @version $Id$
+ * @since 1.7M2
+ */
+public class ImageBlock extends AbstractBlock {
+
+ /**
+ * A reference to the image target. See
+ * {@link org.xwiki.rendering.listener.reference.ResourceReference} for more
+ * details.
+ */
+ private ResourceReference reference;
+
+ /**
+ * If true then the image is defined as a free standing URI directly in the text.
+ */
+ private boolean isFreeStandingURI;
+
+ /**
+ * @param reference
+ * the image reference
+ * @param isFreeStandingURI
+ * indicate if the image syntax is simple a full descriptive syntax (detail depending of
+ * the syntax)
+ * @since 2.5RC1
+ */
+ public ImageBlock(ResourceReference reference, boolean isFreeStandingURI) {
+ this(reference, isFreeStandingURI, Collections.emptyMap());
+ }
+
+ /**
+ * @param reference
+ * the image reference
+ * @param isFreeStandingURI
+ * indicate if the image syntax is simple a full descriptive syntax (detail depending of
+ * the syntax)
+ * @param parameters
+ * the custom parameters
+ * @since 2.5RC1
+ */
+ public ImageBlock(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ super(parameters);
+
+ this.reference = reference;
+ this.isFreeStandingURI = isFreeStandingURI;
+ }
+
+ /**
+ * @return the reference to the image
+ * @see org.xwiki.rendering.listener.reference.ResourceReference
+ * @since 2.5RC1
+ */
+ public ResourceReference getReference() {
+ return this.reference;
+ }
+
+ /**
+ * @return true if the image is defined as a free standing URI directly in the text, false
+ * otherwise
+ */
+ public boolean isFreeStandingURI() {
+ return this.isFreeStandingURI;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onImage(getReference(), isFreeStandingURI(), getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#clone(org.xwiki.rendering.block.BlockFilter)
+ * @since 1.8RC2
+ */
+ @Override
+ public ImageBlock clone(BlockFilter blockFilter) {
+ ImageBlock clone = (ImageBlock) super.clone(blockFilter);
+ clone.reference = getReference().clone();
+ return clone;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/LinkBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/LinkBlock.java
new file mode 100644
index 000000000..52d0a2fb3
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/LinkBlock.java
@@ -0,0 +1,126 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+
+/**
+ * Represents a Link element in a page.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class LinkBlock extends AbstractFatherBlock {
+
+ /**
+ * A reference to the link target. See
+ * {@link org.xwiki.rendering.listener.reference.ResourceReference} for more
+ * details.
+ */
+ private ResourceReference reference;
+
+ /**
+ * If true then the link is a free standing URI directly in the text.
+ */
+ private boolean isFreeStandingURI;
+
+ /**
+ * @param childrenBlocks
+ * the nested children blocks
+ * @param reference
+ * the reference to the target resource to link to
+ * @param isFreeStandingURI
+ * if true then the link is a free standing URI directly in the text
+ * @since 2.5RC1
+ */
+ public LinkBlock(List childrenBlocks, ResourceReference reference, boolean isFreeStandingURI) {
+ this(childrenBlocks, reference, isFreeStandingURI, Collections.emptyMap());
+ }
+
+ /**
+ * @param childrenBlocks
+ * the nested children blocks
+ * @param reference
+ * the reference to the target resource to link to
+ * @param isFreeStandingURI
+ * if true then the link is a free standing URI directly in the text
+ * @param parameters
+ * the parameters to set
+ * @since 2.5RC1
+ */
+ public LinkBlock(List childrenBlocks, ResourceReference reference, boolean isFreeStandingURI,
+ Map parameters) {
+ super(childrenBlocks, parameters);
+ this.reference = reference;
+ this.isFreeStandingURI = isFreeStandingURI;
+ }
+
+ /**
+ * @return the reference to the target to link to
+ * @see org.xwiki.rendering.listener.reference.ResourceReference
+ * @since 2.5RC1
+ */
+ public ResourceReference getReference() {
+ return this.reference;
+ }
+
+ /**
+ * @return true if the link is a free standing URI directly in the text, false otherwise
+ */
+ public boolean isFreeStandingURI() {
+ return this.isFreeStandingURI;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginLink(getReference(), isFreeStandingURI(), getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endLink(getReference(), isFreeStandingURI(), getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#clone(org.xwiki.rendering.block.BlockFilter)
+ * @since 1.8RC2
+ */
+ @Override
+ public LinkBlock clone(BlockFilter blockFilter) {
+ LinkBlock clone = (LinkBlock) super.clone(blockFilter);
+ clone.reference = getReference().clone();
+ return clone;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListBLock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListBLock.java
new file mode 100644
index 000000000..45fd88828
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListBLock.java
@@ -0,0 +1,30 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+/**
+ * Represents any type of Lists (numbered list, bulleted list, etc).
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public interface ListBLock extends Block {
+ // This is currently only a tagging interface and thus it has no methods.
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListItemBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListItemBlock.java
new file mode 100644
index 000000000..7b8bdbde4
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListItemBlock.java
@@ -0,0 +1,61 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a List item element in a page.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class ListItemBlock extends AbstractFatherBlock {
+
+ /**
+ * Constructs a list item Block.
+ *
+ * @param childrenBlocks
+ * the blocks representing the list item content
+ */
+ public ListItemBlock(List childrenBlocks) {
+ super(childrenBlocks);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginListItem();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endListItem();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroBlock.java
new file mode 100644
index 000000000..59e07642c
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroBlock.java
@@ -0,0 +1,128 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a Macro (standalone or inline) defined in a page.
+ *
+ * Note: You can get macro parameters using {@link #getParameters()} for example. Macro block is
+ * reusing Block standard
+ * custom parameters API since macro by definition already have parameters and don't need also block
+ * parameters. So in
+ * this case MacroBlock parameters and Block parameters are the same thing.
+ *
+ * @version $Id$
+ * @since 1.8M2
+ */
+public class MacroBlock extends AbstractBlock {
+
+ /**
+ * @see #getId
+ */
+ private String id;
+
+ /**
+ * The macro content for macro that have content. Otherwise it's null.
+ */
+ private String content;
+
+ /**
+ * The macro is located in a inline content (like paragraph, etc.).
+ */
+ private boolean isInline;
+
+ /**
+ * @param id
+ * the id of the macro
+ * @param parameters
+ * the parameters of the macro
+ * @param isInline
+ * indicate if the macro is located in a inline content (like paragraph, etc.)
+ */
+ public MacroBlock(String id, Map parameters, boolean isInline) {
+ this(id, parameters, null, isInline);
+ }
+
+ /**
+ * @param id
+ * the id of the macro
+ * @param parameters
+ * the parameters of the macro
+ * @param content
+ * the content of the macro. Null if the macro does not have content
+ * @param isInline
+ * indicate if the macro is located in a inline content (like paragraph, etc.)
+ */
+ public MacroBlock(String id, Map parameters, String content, boolean isInline) {
+ super(parameters);
+
+ this.id = id;
+ this.content = content;
+ this.isInline = isInline;
+ }
+
+ /**
+ * @return the macro id (eg "toc" for the TOC Macro).
+ * @since 2.0M3
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * @return the macro content.
+ */
+ public String getContent() {
+ return this.content;
+ }
+
+ /**
+ * @return if true the macro is located in a inline content (like paragraph, etc.).
+ */
+ public boolean isInline() {
+ return this.isInline;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ // Don't do anything here since we want the Macro Transformer component to take in charge
+ // Macro execution. This is because Macro execution is a complex process that involves:
+ // * computing the order in which the macros should be evaluated. For example the TOC macro
+ // should evaluate last since other macros can contribute headers/sections blocks.
+ // * some macros need to modify blocks in the XDOM object
+ // * macro execution is a multi-pass process
+ // In essence the Macro Transformer will replace all MacroBlock blocks with other Blocks
+ // generated from the execution of the Macros when XDOM.traverse() is called there
+ // won't be any MacroBlock.traverse() method called at all.
+
+ // Note: We're calling the event to let other listener downstream decide what to do with it.
+ // In practice as described above this method will never get called when the whole rendering
+ // process is executed. This does get called during our unit tests though.
+ listener.onMacro(getId(), getParameters(), getContent(), isInline());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroMarkerBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroMarkerBlock.java
new file mode 100644
index 000000000..50f0d42db
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroMarkerBlock.java
@@ -0,0 +1,137 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * A special block that Macro Blocks generate when they are executed so that it's possible to
+ * reconstruct the initial
+ * syntax even after Macros have been executed. For example this is important in a WYSWIYG editor
+ * where you want to show
+ * the Macro's rendered result and also let users modify the macro content.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class MacroMarkerBlock extends AbstractFatherBlock {
+
+ /**
+ * The macro name that we are preserving.
+ */
+ private String id;
+
+ /**
+ * The macro content that we are preserving.
+ */
+ private String content;
+
+ /**
+ * The macro is located in a inline content (like paragraph, etc.).
+ */
+ private boolean isInline;
+
+ /**
+ * @param id
+ * the name of the macro
+ * @param parameters
+ * the parameters of the macro
+ * @param childBlocks
+ * the list of children blocks generated by the macro
+ * @param isInline
+ * indicate if the macro is located in a inline content (like paragraph, etc.)
+ */
+ public MacroMarkerBlock(String id, Map parameters, List childBlocks, boolean isInline) {
+ this(id, parameters, null, childBlocks, isInline);
+ }
+
+ /**
+ * @param id
+ * the name of the macro
+ * @param parameters
+ * the parameters of the macro
+ * @param content
+ * the content of the macro. Null if the macro does not have content
+ * @param childBlocks
+ * the list of children blocks generated by the macro
+ * @param isInline
+ * indicate if the macro is located in a inline content (like paragraph, etc.)
+ */
+ public MacroMarkerBlock(String id, Map parameters, String content, List childBlocks,
+ boolean isInline) {
+ super(childBlocks, parameters);
+
+ this.id = id;
+ this.content = content;
+ this.isInline = isInline;
+ }
+
+ /**
+ * @return the macro name.
+ * @deprecated since 2.4M1 use {@link #getId()} instead
+ */
+ @Deprecated
+ public String getName() {
+ return getId();
+ }
+
+ /**
+ * @return the macro identifier.
+ * @since 2.4M1
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * @return the macro content.
+ */
+ public String getContent() {
+ return this.content;
+ }
+
+ /**
+ * @return if true the macro is located in a inline content (like paragraph, etc.).
+ */
+ public boolean isInline() {
+ return this.isInline;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginMacroMarker(getName(), getParameters(), getContent(), isInline());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endMacroMarker(getName(), getParameters(), getContent(), isInline());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NewLineBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NewLineBlock.java
new file mode 100644
index 000000000..f826f88d0
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NewLineBlock.java
@@ -0,0 +1,55 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a new line or line break (it's up to the Renderers to decide if it should be outputted
+ * as a new line or as
+ * a line break in the given syntax).
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public final class NewLineBlock extends AbstractBlock {
+
+ /**
+ * A new line block. Note that we don't make NewLineBlock a singleton since that would cause
+ * problems when using
+ * Block APIs to manipulate a tree of blocks (for example to find the position of a new line block
+ * in a list using
+ * {@link java.util.List#indexOf(Object)} wich would always return the first new line block).
+ *
+ * @since 2.6RC1
+ */
+ public NewLineBlock() {
+ // We need to keep this constructor to override the ones in AbstractBlock
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onNewLine();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NumberedListBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NumberedListBlock.java
new file mode 100644
index 000000000..04d954363
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NumberedListBlock.java
@@ -0,0 +1,77 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.ListType;
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a numbered List.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class NumberedListBlock extends AbstractFatherBlock implements ListBLock {
+
+ /**
+ * Construct a Numbered List Block with no parameters.
+ *
+ * @param childrenBlocks
+ * the blocks making the list
+ */
+ public NumberedListBlock(List childrenBlocks) {
+ super(childrenBlocks);
+ }
+
+ /**
+ * Construct a Numbered List Block with parameters.
+ *
+ * @param childrenBlocks
+ * the blocks making the list
+ * @param parameters
+ * see {@link org.xwiki.rendering.block.AbstractBlock#getParameter(String)} for more
+ * details on
+ * parameters
+ */
+ public NumberedListBlock(List childrenBlocks, Map parameters) {
+ super(childrenBlocks, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginList(ListType.NUMBERED, getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endList(ListType.NUMBERED, getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ParagraphBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ParagraphBlock.java
new file mode 100644
index 000000000..b40eaa611
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ParagraphBlock.java
@@ -0,0 +1,68 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class ParagraphBlock extends AbstractFatherBlock {
+
+ /**
+ * @param blocks
+ * the children blocks of the paragraph
+ */
+ public ParagraphBlock(List blocks) {
+ super(blocks);
+ }
+
+ /**
+ * @param blocks
+ * the children blocks of the paragraph
+ * @param parameters
+ * the parameters of the paragraph
+ */
+ public ParagraphBlock(List blocks, Map parameters) {
+ super(blocks, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginParagraph(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endParagraph(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/PlainTextBlockFilter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/PlainTextBlockFilter.java
new file mode 100644
index 000000000..ebb13a770
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/PlainTextBlockFilter.java
@@ -0,0 +1,109 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+import org.xwiki.rendering.parser.ParseException;
+import org.xwiki.rendering.parser.Parser;
+import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator;
+
+/**
+ * Used to filter plain text blocks.
+ *
+ * @version $Id$
+ * @since 1.9M1
+ */
+public class PlainTextBlockFilter implements BlockFilter {
+
+ /**
+ * The set of valid Block classes as toc item content.
+ */
+ private static final Set> VALID_PLAINTEXT_BLOCKS = new HashSet>() {
+
+ {
+ add(WordBlock.class);
+ add(SpaceBlock.class);
+ add(SpecialSymbolBlock.class);
+ add(NewLineBlock.class);
+ }
+ };
+
+ /**
+ * A parser that knows how to parse plain text; this is used to transform link labels into plain
+ * text.
+ */
+ private Parser plainTextParser;
+
+ /**
+ * Generate link label.
+ */
+ private LinkLabelGenerator linkLabelGenerator;
+
+ /**
+ * @param plainTextParser
+ * a plain text parser used to transform link labels into plain text
+ * @param linkLabelGenerator
+ * generate link label.
+ * @since 2.0M3
+ */
+ public PlainTextBlockFilter(Parser plainTextParser, LinkLabelGenerator linkLabelGenerator) {
+ this.plainTextParser = plainTextParser;
+ this.linkLabelGenerator = linkLabelGenerator;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.BlockFilter#filter(org.xwiki.rendering.block.Block)
+ */
+ public List filter(Block block) {
+ if (VALID_PLAINTEXT_BLOCKS.contains(block.getClass())) {
+ return Collections.singletonList(block);
+ } else if (block.getClass() == LinkBlock.class && block.getChildren().size() == 0) {
+ ResourceReference reference = ((LinkBlock) block).getReference();
+
+ try {
+ String label;
+
+ if (reference.getType().equals(ResourceType.DOCUMENT)) {
+ label = this.linkLabelGenerator.generate(reference);
+ } else {
+ label = reference.getReference();
+ }
+
+ return this.plainTextParser.parse(new StringReader(label)).getChildren().get(0).getChildren();
+ } catch (ParseException e) {
+ // This shouldn't happen since the parser cannot throw an exception since the source is a
+ // memory
+ // String.
+ throw new RuntimeException("Failed to parse link label as plain text", e);
+ }
+ } else {
+ return Collections.emptyList();
+ }
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationBlock.java
new file mode 100644
index 000000000..b6111659d
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationBlock.java
@@ -0,0 +1,71 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a quotation. There are one or several quotation lines inside a quotation block.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class QuotationBlock extends AbstractFatherBlock {
+
+ /**
+ * @param blocks
+ * the children of the quotation
+ */
+ public QuotationBlock(List blocks) {
+ super(blocks, Collections.emptyMap());
+ }
+
+ /**
+ * @param blocks
+ * the children of the quotation
+ * @param parameters
+ * the parameters of the quotation
+ */
+ public QuotationBlock(List blocks, Map parameters) {
+ super(blocks, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginQuotation(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endQuotation(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationLineBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationLineBlock.java
new file mode 100644
index 000000000..df20ff420
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationLineBlock.java
@@ -0,0 +1,59 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a quotation line. There can be several quotation lines in a quotation block.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class QuotationLineBlock extends AbstractFatherBlock {
+
+ /**
+ * @param blocks
+ * the children of the quotation line
+ */
+ public QuotationLineBlock(List blocks) {
+ super(blocks);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginQuotationLine();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endQuotationLine();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/RawBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/RawBlock.java
new file mode 100644
index 000000000..f94f7cad8
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/RawBlock.java
@@ -0,0 +1,80 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+import org.xwiki.rendering.syntax.Syntax;
+
+/**
+ * Represents some raw content that shouldn't be parsed or modified and that should be injected as
+ * is in any output. The
+ * content depends on a syntax and listeners decide if they can handle that syntax or not. For
+ * example if it's in
+ * "xhtml/1.0" syntax then the XHTML Renderer can insert it directly in the XHTML output.
+ *
+ * @version $Id$
+ * @since 1.8.3
+ */
+public class RawBlock extends AbstractBlock {
+
+ /**
+ * @see #getRawContent()
+ */
+ private String rawContent;
+
+ /**
+ * @see #getSyntax()
+ */
+ private Syntax syntax;
+
+ /**
+ * @param rawContent
+ * the content to inject as is into the listener (it won't be modified)
+ * @param syntax
+ * the syntax in which the content is written
+ */
+ public RawBlock(String rawContent, Syntax syntax) {
+ this.rawContent = rawContent;
+ this.syntax = syntax;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractBlock#traverse(Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onRawText(getRawContent(), getSyntax());
+ }
+
+ /**
+ * @return the content to inject as is into the listener (it won't be modified)
+ */
+ public String getRawContent() {
+ return this.rawContent;
+ }
+
+ /**
+ * @return the syntax in which the content is written
+ */
+ public Syntax getSyntax() {
+ return this.syntax;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SectionBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SectionBlock.java
new file mode 100644
index 000000000..20f1346a3
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SectionBlock.java
@@ -0,0 +1,86 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class SectionBlock extends AbstractFatherBlock {
+
+ /**
+ * @param childBlocks
+ * the children of the section
+ */
+ public SectionBlock(List childBlocks) {
+ super(childBlocks);
+ }
+
+ /**
+ * @param childBlocks
+ * the children of the section
+ * @param parameters
+ * the parameters of the section
+ */
+ public SectionBlock(List childBlocks, Map parameters) {
+ super(childBlocks, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginSection(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endSection(getParameters());
+ }
+
+ /**
+ * @return the title block of the section.
+ */
+ public HeaderBlock getHeaderBlock() {
+ HeaderBlock headerBlock = null;
+
+ List children = getChildren();
+
+ if (children.size() > 0) {
+ Block firstChild = children.get(0);
+ if (firstChild instanceof HeaderBlock) {
+ headerBlock = (HeaderBlock) firstChild;
+ }
+ }
+
+ return headerBlock;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpaceBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpaceBlock.java
new file mode 100644
index 000000000..051bde552
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpaceBlock.java
@@ -0,0 +1,63 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a space.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public final class SpaceBlock extends AbstractBlock {
+
+ /**
+ * A space block. Note that we don't make SpaceBlock a singleton since that would cause problems
+ * when using Block
+ * APIs to manipulate a tree of blocks (for example to find the position of a space block in a
+ * list using
+ * {@link java.util.List#indexOf(Object)} wich would always return the first space block).
+ *
+ * @since 2.6RC1
+ */
+ public SpaceBlock() {
+ // We need to keep this constructor to override the ones in AbstractBlock
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onSpace();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#clone()
+ */
+ @Override
+ public Block clone() {
+ return this;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpecialSymbolBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpecialSymbolBlock.java
new file mode 100644
index 000000000..128b53d2d
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpecialSymbolBlock.java
@@ -0,0 +1,71 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represent a non-alphanumeric and non-space symbol (>, ]...).
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class SpecialSymbolBlock extends AbstractBlock {
+
+ /**
+ * The symbol.
+ */
+ private char symbol;
+
+ /**
+ * @param symbol
+ * the symbol
+ */
+ public SpecialSymbolBlock(char symbol) {
+ this.symbol = symbol;
+ }
+
+ /**
+ * @return the symbol
+ */
+ public char getSymbol() {
+ return this.symbol;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.Block#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onSpecialSymbol(getSymbol());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ * @since 1.8RC2
+ */
+ @Override
+ public String toString() {
+ return String.valueOf(getSymbol());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableBlock.java
new file mode 100644
index 000000000..ef09b7653
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableBlock.java
@@ -0,0 +1,63 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a table.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class TableBlock extends AbstractFatherBlock {
+
+ /**
+ * @param list
+ * the list of children blocks of the table block (generally a list of
+ * {@link TableRowBlock}).
+ * @param parameters
+ * the parameters of the table.
+ */
+ public TableBlock(List list, Map parameters) {
+ super(list, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginTable(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endTable(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableCellBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableCellBlock.java
new file mode 100644
index 000000000..9526c05e6
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableCellBlock.java
@@ -0,0 +1,62 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a cell of a table.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class TableCellBlock extends AbstractFatherBlock {
+
+ /**
+ * @param list
+ * the list of children blocks of the table head cell block.
+ * @param parameters
+ * the parameters of the table row.
+ */
+ public TableCellBlock(List list, Map parameters) {
+ super(list, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginTableCell(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endTableCell(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableHeadCellBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableHeadCellBlock.java
new file mode 100644
index 000000000..62bbe628a
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableHeadCellBlock.java
@@ -0,0 +1,64 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a head of a row or column of a table.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class TableHeadCellBlock extends TableCellBlock {
+
+ /**
+ * @param list
+ * the list of children blocks of the table cell block.
+ * @param parameters
+ * the parameters of the table head cell.
+ */
+ public TableHeadCellBlock(List list, Map parameters) {
+ super(list, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.TableCellBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ @Override
+ public void before(Listener listener) {
+ listener.beginTableHeadCell(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.TableCellBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ @Override
+ public void after(Listener listener) {
+ listener.endTableHeadCell(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableRowBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableRowBlock.java
new file mode 100644
index 000000000..c7ac7b99f
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableRowBlock.java
@@ -0,0 +1,63 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.List;
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents the row of a table. Contains {@link TableCellBlock} objects.
+ *
+ * @version $Id$
+ * @since 1.6M2
+ */
+public class TableRowBlock extends AbstractFatherBlock {
+
+ /**
+ * @param list
+ * the list of children blocks of the table row block (generally a list of
+ * {@link TableCellBlock}).
+ * @param parameters
+ * the parameters of the table row.
+ */
+ public TableRowBlock(List list, Map parameters) {
+ super(list, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginTableRow(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endTableRow(getParameters());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/VerbatimBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/VerbatimBlock.java
new file mode 100644
index 000000000..c0fcde9d2
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/VerbatimBlock.java
@@ -0,0 +1,103 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import java.util.Map;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * A Verbatim block.
+ *
+ * @version $Id$
+ * @since 1.8M2
+ */
+public class VerbatimBlock extends AbstractBlock {
+
+ /**
+ * The string to protect from rendering.
+ */
+ private String protectedString;
+
+ /**
+ * If true the macro is located in a inline content (like paragraph, etc.).
+ */
+ private boolean isInline;
+
+ /**
+ * @param protectedString
+ * the string to protect from rendering.
+ * @param isInline
+ * if true the macro is located in a inline content (like paragraph, etc.).
+ */
+ public VerbatimBlock(String protectedString, boolean isInline) {
+ this.protectedString = protectedString;
+ this.isInline = isInline;
+ }
+
+ /**
+ * @param protectedString
+ * the string to protect from rendering.
+ * @param parameters
+ * the custom parameters
+ * @param isInline
+ * if true the macro is located in a inline content (like paragraph, etc.).
+ */
+ public VerbatimBlock(String protectedString, Map parameters, boolean isInline) {
+ super(parameters);
+
+ this.protectedString = protectedString;
+ this.isInline = isInline;
+ }
+
+ /**
+ * @return the string to protect from rendering
+ */
+ public String getProtectedString() {
+ return this.protectedString;
+ }
+
+ /**
+ * @return if true the macro is located in a inline content (like paragraph, etc.).
+ */
+ public boolean isInline() {
+ return this.isInline;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onVerbatim(getProtectedString(), isInline(), getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ * @since 1.8RC2
+ */
+ @Override
+ public String toString() {
+ return getProtectedString();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/WordBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/WordBlock.java
new file mode 100644
index 000000000..f4baf4454
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/WordBlock.java
@@ -0,0 +1,73 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+
+/**
+ * Represents a word.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class WordBlock extends AbstractBlock {
+
+ /**
+ * @see #getWord()
+ */
+ private String word;
+
+ /**
+ * @param word
+ * the word wrapped by this block. Note that this is supposed to be a single word and
+ * space or special
+ * symbols should be represented by other blocks
+ */
+ public WordBlock(String word) {
+ this.word = word;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractBlock#traverse(Listener)
+ */
+ public void traverse(Listener listener) {
+ listener.onWord(getWord());
+ }
+
+ /**
+ * @return the word wrapped by this block
+ */
+ public String getWord() {
+ return this.word;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ * @since 1.8RC2
+ */
+ @Override
+ public String toString() {
+ return getWord();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/XDOM.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/XDOM.java
new file mode 100644
index 000000000..b4a89712e
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/XDOM.java
@@ -0,0 +1,132 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.block;
+
+import org.xwiki.rendering.listener.Listener;
+import org.xwiki.rendering.util.IdGenerator;
+
+import java.util.List;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Contains the full tree of {@link Block} that represent a XWiki Document's content.
+ *
+ * @version $Id$
+ * @since 1.5M2
+ */
+public class XDOM extends AbstractFatherBlock {
+
+ /**
+ * Constructs an empty XDOM. Useful for example when calling a macro that doesn't use the XDOM
+ * parameter passed to
+ * it.
+ */
+ public static final XDOM EMPTY = new XDOM(Collections.emptyList());
+
+ /**
+ * Stateful id generator for this document. We store it in the XDOM because it is the only object
+ * which remains the
+ * same between parsing, transformation and rendering, and we need to generate ids during parsing
+ * and during
+ * transformation.
+ */
+ private IdGenerator idGenerator;
+
+ /**
+ * @param childBlocks
+ * the list of children blocks of the block to construct
+ * @param parameters
+ * the parameters to set
+ * @see AbstractFatherBlock#AbstractFatherBlock(List)
+ */
+ public XDOM(List childBlocks, Map parameters) {
+ super(childBlocks, parameters);
+
+ this.idGenerator = new IdGenerator();
+ }
+
+ /**
+ * @param childBlocks
+ * the list of children blocks of the block to construct
+ * @see AbstractFatherBlock#AbstractFatherBlock(List)
+ */
+ public XDOM(List childBlocks) {
+ super(childBlocks);
+
+ this.idGenerator = new IdGenerator();
+ }
+
+ /**
+ * @param childBlocks
+ * the list of children blocks of the block to construct
+ * @param idGenerator
+ * a sateful id generator for this document
+ */
+ public XDOM(List childBlocks, IdGenerator idGenerator) {
+ super(childBlocks);
+
+ this.idGenerator = idGenerator;
+ }
+
+ /**
+ * @return a stateful id generator for the whole document.
+ */
+ public IdGenerator getIdGenerator() {
+ return this.idGenerator;
+ }
+
+ /**
+ * @param idGenerator
+ * a stateful id generator for the whole document.
+ * @since 2.1M1
+ */
+ public void setIdGenerator(IdGenerator idGenerator) {
+ this.idGenerator = idGenerator;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener)
+ */
+ public void before(Listener listener) {
+ listener.beginDocument(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener)
+ */
+ public void after(Listener listener) {
+ listener.endDocument(getParameters());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.AbstractBlock#clone()
+ */
+ @Override
+ public XDOM clone() {
+ return (XDOM) super.clone();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/configuration/RenderingConfiguration.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/configuration/RenderingConfiguration.java
new file mode 100644
index 000000000..ce64c1753
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/configuration/RenderingConfiguration.java
@@ -0,0 +1,77 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.configuration;
+
+import org.xwiki.component.annotation.ComponentRole;
+import org.xwiki.rendering.transformation.Transformation;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Configuration properties for the Rendering module.
+ *
+ * You can override the default values for each of the configuration properties below by defining
+ * them in XWiki's global
+ * configuration file using a prefix of "rendering" followed by the property name. For example:
+ * rendering.linkLabelFormat = %s.%p
+ *
+ * @version $Id$
+ * @since 1.6M1
+ */
+@ComponentRole
+public interface RenderingConfiguration {
+
+ /**
+ * A link label format is the format used to decide how to display links that have no label. By
+ * default the page
+ * name is displayed. However it's possible to customize it using the following tokens:
+ *
+ * - %w: wiki name
+ * - %s: space name
+ * - %p: page name
+ * - %P: page name with spaces between camel case words, i.e. "My Page" if the
+ * page name is
+ * "MyPage"
+ * - %t: page title
+ *
+ * Note that if the page title is empty or not defined then it defaults to %p. This is also the
+ * case if the title
+ * cannot be retrieved for the document. The default is "%p". Some examples: "%s.%p", "%w:%s.%p".
+ *
+ * @return the format to use to display link labels when the user hasn't specified a label
+ */
+ String getLinkLabelFormat();
+
+ /**
+ * @return the list of InterWiki definitions. Each InterWiki definition is made of an alias and a
+ * base URL.
+ * @see org.xwiki.rendering.listener.reference.InterWikiResourceReference
+ */
+ Properties getInterWikiDefinitions();
+
+ /**
+ * @return the list of transformations to execute when rendering document content, ordered by
+ * transformation
+ * priority (highest priority first)
+ * @since 2.6RC1
+ */
+ List getTransformations();
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/ConversionException.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/ConversionException.java
new file mode 100644
index 000000000..a4fec547d
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/ConversionException.java
@@ -0,0 +1,60 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.converter;
+
+/**
+ * Encapsulate a conversion error.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+public class ConversionException extends Exception {
+
+ /**
+ * Class ID for serialization.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Construct a new ParseException with the specified detail message.
+ *
+ * @param message
+ * The detailed message. This can later be retrieved by the Throwable.getMessage()
+ * method.
+ */
+ public ConversionException(String message) {
+ super(message);
+ }
+
+ /**
+ * Construct a new ParseException with the specified detail message and cause.
+ *
+ * @param message
+ * The detailed message. This can later be retrieved by the Throwable.getMessage()
+ * method.
+ * @param throwable
+ * the cause. This can be retrieved later by the Throwable.getCause() method. (A null
+ * value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ */
+ public ConversionException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/Converter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/Converter.java
new file mode 100644
index 000000000..c023971ca
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/Converter.java
@@ -0,0 +1,53 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.converter;
+
+import java.io.Reader;
+import org.xwiki.component.annotation.ComponentRole;
+import org.xwiki.rendering.syntax.Syntax;
+import org.xwiki.rendering.renderer.printer.WikiPrinter;
+
+/**
+ * Convert source content in a given Syntax to another Syntax.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@ComponentRole
+public interface Converter {
+
+ /**
+ * Converts content from a Syntax to another and execute all registered Macro Transformations on
+ * the parsed content.
+ *
+ * @param source
+ * the content to be converted
+ * @param sourceSyntax
+ * the Syntax in which the content is represented
+ * @param targetSyntax
+ * the Syntax to which to convert to
+ * @param printer
+ * the printer that will receive the result of the conversion
+ * @throws ConversionException
+ * in case of a conversion error (invalid Syntax, etc)
+ */
+ void convert(Reader source, Syntax sourceSyntax, Syntax targetSyntax, WikiPrinter printer)
+ throws ConversionException;
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/block/ProtectedBlockFilter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/block/ProtectedBlockFilter.java
new file mode 100644
index 000000000..6e2241c6b
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/block/ProtectedBlockFilter.java
@@ -0,0 +1,116 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.block;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.xwiki.rendering.block.Block;
+import org.xwiki.rendering.block.BlockFilter;
+import org.xwiki.rendering.block.MacroMarkerBlock;
+
+/**
+ * Used to manipulate Blocks but by filtering out protected blocks.
+ *
+ * Note: This API is a work in progress and currently a protected block is a code macro marker
+ * block. In the future we
+ * need to make this more generic and since we also need to review Transformations to make them more
+ * performant this
+ * class may go away which is why it's currently located in an internal package.
+ *
+ *
+ * @version $Id$
+ * @since 2.6
+ */
+public class ProtectedBlockFilter implements BlockFilter {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.block.BlockFilter#filter(org.xwiki.rendering.block.Block)
+ */
+ public List filter(Block block) {
+ List blocks = new ArrayList();
+ if (!isProtectedBlock(block)) {
+ blocks.add(block);
+ }
+ return blocks;
+ }
+
+ /**
+ * @param blocks
+ * the blocks to filter
+ * @return the filtered blocks
+ */
+ public List filter(List blocks) {
+ List filteredBlocks = new ArrayList();
+ for (Block block : blocks) {
+ filteredBlocks.addAll(filter(block));
+ }
+ return filteredBlocks;
+ }
+
+ /**
+ * @param block
+ * the block to filter out
+ * @return the next sibling that is not a protected block or null if not found
+ */
+ public Block getNextSibling(Block block) {
+ Block sibling = block.getNextSibling();
+ while (sibling != null && isProtectedBlock(sibling)) {
+ sibling = sibling.getNextSibling();
+ }
+ return sibling;
+ }
+
+ /**
+ * @param block
+ * the block to filter out
+ * @param blockClass
+ * the type of Blocks to look for
+ * @param recurse
+ * if true also search recursively children
+ * @param
+ * the class of the Blocks to return
+ * @return the filtered blocks matching the passed Block class
+ */
+ public List getChildrenByType(Block block, Class blockClass, boolean recurse) {
+ List typedBlocks = new ArrayList();
+ for (Block child : filter(block.getChildren())) {
+ if (blockClass.isAssignableFrom(child.getClass())) {
+ typedBlocks.add(blockClass.cast(child));
+ }
+ if (recurse && !child.getChildren().isEmpty()) {
+ typedBlocks.addAll(getChildrenByType(child, blockClass, true));
+ }
+ }
+
+ return typedBlocks;
+ }
+
+ /**
+ * @param block
+ * the block to test
+ * @return true if the passed block is a protected block or false otherwise
+ */
+ private boolean isProtectedBlock(Block block) {
+ return (block instanceof MacroMarkerBlock) && ((MacroMarkerBlock) block).getId().equals("code");
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/configuration/DefaultRenderingConfiguration.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/configuration/DefaultRenderingConfiguration.java
new file mode 100644
index 000000000..717e9a7af
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/configuration/DefaultRenderingConfiguration.java
@@ -0,0 +1,127 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.configuration;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.phase.Initializable;
+import org.xwiki.component.phase.InitializationException;
+import org.xwiki.rendering.configuration.RenderingConfiguration;
+import org.xwiki.rendering.transformation.Transformation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Basic default implementation to be used when using the XWiki Rendering system standalone.
+ *
+ * @version $Id$
+ * @since 2.0M1
+ */
+@Component
+public class DefaultRenderingConfiguration implements RenderingConfiguration, Initializable {
+
+ /**
+ * Holds the list of transformations to apply, sorted by priority in {@link #initialize()}.
+ */
+ @Requirement
+ private List transformations = new ArrayList();
+
+ /**
+ * @see #getLinkLabelFormat()
+ */
+ private String linkLabelFormat = "%p";
+
+ /**
+ * @see #getInterWikiDefinitions()
+ */
+ private Properties interWikiDefinitions = new Properties();
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Initializable#initialize()
+ */
+ public void initialize() throws InitializationException {
+ // Sort transformations by priority.
+ Collections.sort(this.transformations);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.configuration.RenderingConfiguration#getLinkLabelFormat()
+ */
+ public String getLinkLabelFormat() {
+ return this.linkLabelFormat;
+ }
+
+ /**
+ * @param linkLabelFormat
+ * the format used to decide how to display links that have no label
+ */
+ public void setLinkLabelFormat(String linkLabelFormat) {
+ // This method is useful for those using the XWiki Rendering in standalone mode since it allows
+ // the rendering
+ // to work even without a configuration store.
+ this.linkLabelFormat = linkLabelFormat;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.configuration.RenderingConfiguration#getInterWikiDefinitions()
+ */
+ public Properties getInterWikiDefinitions() {
+ return this.interWikiDefinitions;
+ }
+
+ /**
+ * @param interWikiAlias
+ * see {@link org.xwiki.rendering.listener.reference.InterWikiResourceReference}
+ * @param interWikiURL
+ * see {@link org.xwiki.rendering.listener.reference.InterWikiResourceReference}
+ */
+ public void addInterWikiDefinition(String interWikiAlias, String interWikiURL) {
+ // This method is useful for those using the XWiki Rendering in standalone mode since it allows
+ // the rendering
+ // to work even without a configuration store.
+ this.interWikiDefinitions.setProperty(interWikiAlias, interWikiURL);
+ }
+
+ /**
+ * @param transformations
+ * the explicit list of transformations to execute (overrides the default list)
+ */
+ public void setTransformations(List transformations) {
+ this.transformations = transformations;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.configuration.RenderingConfiguration#getTransformations()
+ */
+ public List getTransformations() {
+ return this.transformations;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/converter/DefaultConverter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/converter/DefaultConverter.java
new file mode 100644
index 000000000..e41c5b7b3
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/converter/DefaultConverter.java
@@ -0,0 +1,77 @@
+package org.xwiki.rendering.internal.converter;
+
+import java.io.Reader;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentManager;
+import org.xwiki.rendering.block.XDOM;
+import org.xwiki.rendering.converter.ConversionException;
+import org.xwiki.rendering.converter.Converter;
+import org.xwiki.rendering.parser.ParseException;
+import org.xwiki.rendering.parser.Parser;
+import org.xwiki.rendering.syntax.Syntax;
+import org.xwiki.rendering.renderer.BlockRenderer;
+import org.xwiki.rendering.renderer.printer.WikiPrinter;
+import org.xwiki.rendering.transformation.TransformationContext;
+import org.xwiki.rendering.transformation.TransformationException;
+import org.xwiki.rendering.transformation.TransformationManager;
+
+/**
+ * Default implementation for {@link Converter}.
+ *
+ * @version $Id$
+ */
+@Component
+public class DefaultConverter implements Converter {
+
+ /**
+ * Used to lookup parser and renderer.
+ */
+ @Requirement
+ private ComponentManager componentManager;
+
+ /**
+ * Used to execute transformations.
+ */
+ @Requirement
+ private TransformationManager transformationManager;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.converter.Converter#convert(java.io.Reader,
+ * org.xwiki.rendering.syntax.Syntax,
+ * org.xwiki.rendering.syntax.Syntax, org.xwiki.rendering.renderer.printer.WikiPrinter)
+ */
+ public void convert(Reader source, Syntax sourceSyntax, Syntax targetSyntax, WikiPrinter printer)
+ throws ConversionException {
+ // Step 1: Find the parser and generate a XDOM
+ XDOM xdom;
+ try {
+ Parser parser = this.componentManager.lookup(Parser.class, sourceSyntax.toIdString());
+ xdom = parser.parse(source);
+ } catch (ComponentLookupException e) {
+ throw new ConversionException("Failed to locate Parser for syntax [" + sourceSyntax + "]", e);
+ } catch (ParseException e) {
+ throw new ConversionException("Failed to parse input source", e);
+ }
+
+ // Step 2: Run transformations
+ try {
+ TransformationContext context = new TransformationContext(xdom, sourceSyntax);
+ this.transformationManager.performTransformations(xdom, context);
+ } catch (TransformationException e) {
+ throw new ConversionException("Failed to execute some transformations", e);
+ }
+
+ // Step 3: Locate the Renderer and render the content in the passed printer
+ BlockRenderer renderer;
+ try {
+ renderer = this.componentManager.lookup(BlockRenderer.class, targetSyntax.toIdString());
+ } catch (ComponentLookupException e) {
+ throw new ConversionException("Failed to locate Renderer for syntax [" + targetSyntax + "]", e);
+ }
+ renderer.render(xdom, printer);
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/AbstractBlockParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/AbstractBlockParser.java
new file mode 100644
index 000000000..37318c70e
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/AbstractBlockParser.java
@@ -0,0 +1,73 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser;
+
+import java.io.Reader;
+
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentManager;
+import org.xwiki.rendering.block.XDOM;
+import org.xwiki.rendering.parser.ParseException;
+import org.xwiki.rendering.parser.Parser;
+import org.xwiki.rendering.parser.StreamParser;
+
+/**
+ * Common code for {@link Parser} implementation that produce a {@link XDOM} from
+ * {@link StreamParser}.
+ *
+ * @version $Id$
+ * @since 2.1M1
+ */
+public abstract class AbstractBlockParser implements Parser {
+
+ /**
+ * Used to lookup the {@link StreamParser} for the syntax.
+ */
+ @Requirement
+ private ComponentManager componentManager;
+
+ /**
+ * @return the {@link StreamParser} to use to parser the input content
+ */
+ protected StreamParser getStreamParser() {
+ StreamParser streamParser;
+ try {
+ streamParser = this.componentManager.lookup(StreamParser.class, getSyntax().toIdString());
+ } catch (ComponentLookupException e) {
+ throw new RuntimeException("Failed to create [" + getSyntax().toString() + "] renderer", e);
+ }
+
+ return streamParser;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.parser.Parser#parse(java.io.Reader)
+ */
+ public XDOM parse(Reader source) throws ParseException {
+ XDOMGeneratorListener listener = new XDOMGeneratorListener();
+
+ getStreamParser().parse(source, listener);
+
+ return listener.getXDOM();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextBlockParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextBlockParser.java
new file mode 100644
index 000000000..d1d138e6e
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextBlockParser.java
@@ -0,0 +1,42 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.syntax.Syntax;
+
+/**
+ * Plain Text Parser to convert a text source into a XDOM object.
+ *
+ * @version $Id$
+ * @since 2.1M1
+ */
+@Component("plain/1.0")
+public class PlainTextBlockParser extends AbstractBlockParser {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.parser.Parser#getSyntax()
+ */
+ public Syntax getSyntax() {
+ return Syntax.PLAIN_1_0;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextStreamParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextStreamParser.java
new file mode 100644
index 000000000..9b8761a32
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextStreamParser.java
@@ -0,0 +1,128 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.regex.Pattern;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.Listener;
+import org.xwiki.rendering.parser.ParseException;
+import org.xwiki.rendering.parser.StreamParser;
+import org.xwiki.rendering.syntax.Syntax;
+
+/**
+ * Plain Text Parser to convert a text source into a events.
+ *
+ * @version $Id$
+ * @since 2.1M1
+ */
+@Component("plain/1.0")
+public class PlainTextStreamParser implements StreamParser {
+
+ /**
+ * The characters which are considered as "special" symbols for
+ * {@link org.xwiki.rendering.block.SpecialSymbolBlock}
+ * .
+ */
+ public static final Pattern SPECIALSYMBOL_PATTERN = Pattern.compile("[!\"#$%&'()*+,-./:;<=>?@\\[\\]^_`{|}~]");
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.parser.Parser#getSyntax()
+ */
+ public Syntax getSyntax() {
+ return Syntax.PLAIN_1_0;
+ }
+
+ /**
+ * Read a single char from an Reader source.
+ *
+ * @param source
+ * the input to read from
+ * @return the char read
+ * @throws ParseException
+ * in case of reading error
+ */
+ private int readChar(Reader source) throws ParseException {
+ int c;
+
+ try {
+ c = source.read();
+ } catch (IOException e) {
+ throw new ParseException("Failed to read input source", e);
+ }
+
+ return c;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.parser.StreamParser#parse(java.io.Reader,
+ * org.xwiki.rendering.listener.Listener)
+ */
+ public void parse(Reader source, Listener listener) throws ParseException {
+ StringBuffer word = new StringBuffer();
+ BufferedReader bufferedSource = new BufferedReader(source);
+ int charAsInt;
+
+ listener.beginParagraph(Listener.EMPTY_PARAMETERS);
+
+ while ((charAsInt = readChar(bufferedSource)) != -1) {
+ char c = (char) charAsInt;
+ if (c == '\n') {
+ if (word.length() > 0) {
+ listener.onWord(word.toString());
+ }
+ listener.onNewLine();
+
+ word.setLength(0);
+ } else if (c == '\r') {
+ // Do nothing, skip it
+ } else if (c == ' ') {
+ if (word.length() > 0) {
+ listener.onWord(word.toString());
+ }
+ listener.onSpace();
+
+ word.setLength(0);
+ } else if (SPECIALSYMBOL_PATTERN.matcher(String.valueOf(c)).matches()) {
+ if (word.length() > 0) {
+ listener.onWord(word.toString());
+ }
+ listener.onSpecialSymbol(c);
+
+ word.setLength(0);
+ } else {
+ word.append(c);
+ }
+ }
+
+ if (word.length() > 0) {
+ listener.onWord(word.toString());
+ }
+
+ listener.endParagraph(Listener.EMPTY_PARAMETERS);
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/XDOMGeneratorListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/XDOMGeneratorListener.java
new file mode 100644
index 000000000..df980cbff
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/XDOMGeneratorListener.java
@@ -0,0 +1,571 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.xwiki.rendering.block.AbstractBlock;
+import org.xwiki.rendering.block.Block;
+import org.xwiki.rendering.block.BulletedListBlock;
+import org.xwiki.rendering.block.DefinitionDescriptionBlock;
+import org.xwiki.rendering.block.DefinitionListBlock;
+import org.xwiki.rendering.block.DefinitionTermBlock;
+import org.xwiki.rendering.block.EmptyLinesBlock;
+import org.xwiki.rendering.block.FormatBlock;
+import org.xwiki.rendering.block.GroupBlock;
+import org.xwiki.rendering.block.HeaderBlock;
+import org.xwiki.rendering.block.HorizontalLineBlock;
+import org.xwiki.rendering.block.IdBlock;
+import org.xwiki.rendering.block.ImageBlock;
+import org.xwiki.rendering.block.LinkBlock;
+import org.xwiki.rendering.block.ListItemBlock;
+import org.xwiki.rendering.block.MacroBlock;
+import org.xwiki.rendering.block.MacroMarkerBlock;
+import org.xwiki.rendering.block.NewLineBlock;
+import org.xwiki.rendering.block.NumberedListBlock;
+import org.xwiki.rendering.block.ParagraphBlock;
+import org.xwiki.rendering.block.QuotationBlock;
+import org.xwiki.rendering.block.QuotationLineBlock;
+import org.xwiki.rendering.block.RawBlock;
+import org.xwiki.rendering.block.SectionBlock;
+import org.xwiki.rendering.block.SpaceBlock;
+import org.xwiki.rendering.block.SpecialSymbolBlock;
+import org.xwiki.rendering.block.TableBlock;
+import org.xwiki.rendering.block.TableCellBlock;
+import org.xwiki.rendering.block.TableHeadCellBlock;
+import org.xwiki.rendering.block.TableRowBlock;
+import org.xwiki.rendering.block.VerbatimBlock;
+import org.xwiki.rendering.block.WordBlock;
+import org.xwiki.rendering.block.XDOM;
+import org.xwiki.rendering.listener.Format;
+import org.xwiki.rendering.listener.HeaderLevel;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.ListType;
+import org.xwiki.rendering.listener.Listener;
+import org.xwiki.rendering.syntax.Syntax;
+
+/**
+ * Produce a {@link XDOM} based on events.
+ *
+ * @version $Id$
+ * @since 2.1M1
+ */
+public class XDOMGeneratorListener implements Listener {
+
+ private Stack stack = new Stack();
+
+ private final MarkerBlock marker = new MarkerBlock();
+
+ private static class MarkerBlock extends AbstractBlock {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractBlock#traverse(Listener)
+ */
+ public void traverse(Listener listener) {
+ // Nothing to do since this block is only used as a marker.
+ }
+ }
+
+ public XDOM getXDOM() {
+ return new XDOM(generateListFromStack());
+ }
+
+ private List generateListFromStack() {
+ List blocks = new ArrayList();
+ while (!this.stack.empty()) {
+ if (this.stack.peek() != this.marker) {
+ blocks.add(this.stack.pop());
+ } else {
+ this.stack.pop();
+ break;
+ }
+ }
+ Collections.reverse(blocks);
+ return blocks;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginDefinitionDescription()
+ */
+ public void beginDefinitionDescription() {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map)
+ */
+ public void beginDefinitionList(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginDefinitionTerm()
+ */
+ public void beginDefinitionTerm() {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map)
+ */
+ public void beginDocument(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginFormat(org.xwiki.rendering.listener.Format,
+ * java.util.Map)
+ */
+ public void beginFormat(Format format, Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginGroup(java.util.Map)
+ */
+ public void beginGroup(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginHeader(org.xwiki.rendering.listener.HeaderLevel,
+ * java.lang.String, java.util.Map)
+ */
+ public void beginHeader(HeaderLevel level, String id, Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginList(org.xwiki.rendering.listener.ListType,
+ * java.util.Map)
+ */
+ public void beginList(ListType listType, Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginListItem()
+ */
+ public void beginListItem() {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginMacroMarker(java.lang.String, java.util.Map,
+ * java.lang.String,
+ * boolean)
+ */
+ public void beginMacroMarker(String name, Map macroParameters, String content, boolean isInline) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginParagraph(java.util.Map)
+ */
+ public void beginParagraph(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginQuotation(java.util.Map)
+ */
+ public void beginQuotation(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginQuotationLine()
+ */
+ public void beginQuotationLine() {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginSection(java.util.Map)
+ */
+ public void beginSection(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map)
+ */
+ public void beginTable(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map)
+ */
+ public void beginTableCell(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map)
+ */
+ public void beginTableHeadCell(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map)
+ */
+ public void beginTableRow(Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.LinkListener#beginLink(org.xwiki.rendering.listener.reference.ResourceReference
+ * , boolean, java.util.Map)
+ */
+ public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ this.stack.push(this.marker);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endDefinitionDescription()
+ */
+ public void endDefinitionDescription() {
+ this.stack.push(new DefinitionDescriptionBlock(generateListFromStack()));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endDefinitionList(java.util.Map)
+ */
+ public void endDefinitionList(Map parameters) {
+ this.stack.push(new DefinitionListBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endDefinitionTerm()
+ */
+ public void endDefinitionTerm() {
+ this.stack.push(new DefinitionTermBlock(generateListFromStack()));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map)
+ */
+ public void endDocument(Map parameters) {
+ // Do nothing. This is supposed to append only once for the hole document
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endFormat(org.xwiki.rendering.listener.Format,
+ * java.util.Map)
+ */
+ public void endFormat(Format format, Map parameters) {
+ this.stack.push(new FormatBlock(generateListFromStack(), format, parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endGroup(java.util.Map)
+ */
+ public void endGroup(Map parameters) {
+ this.stack.push(new GroupBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endHeader(org.xwiki.rendering.listener.HeaderLevel,
+ * java.lang.String,
+ * java.util.Map)
+ */
+ public void endHeader(HeaderLevel level, String id, Map parameters) {
+ this.stack.push(new HeaderBlock(generateListFromStack(), level, parameters, id));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endList(org.xwiki.rendering.listener.ListType,
+ * java.util.Map)
+ */
+ public void endList(ListType listType, Map parameters) {
+ if (listType == ListType.BULLETED) {
+ this.stack.push(new BulletedListBlock(generateListFromStack(), parameters));
+ } else {
+ this.stack.push(new NumberedListBlock(generateListFromStack(), parameters));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endListItem()
+ */
+ public void endListItem() {
+ this.stack.push(new ListItemBlock(generateListFromStack()));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endMacroMarker(java.lang.String, java.util.Map,
+ * java.lang.String,
+ * boolean)
+ */
+ public void endMacroMarker(String name, Map macroParameters, String content, boolean isInline) {
+ this.stack.push(new MacroMarkerBlock(name, macroParameters, content, generateListFromStack(), isInline));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endParagraph(java.util.Map)
+ */
+ public void endParagraph(Map parameters) {
+ this.stack.push(new ParagraphBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endQuotation(java.util.Map)
+ */
+ public void endQuotation(Map parameters) {
+ this.stack.push(new QuotationBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endQuotationLine()
+ */
+ public void endQuotationLine() {
+ this.stack.push(new QuotationLineBlock(generateListFromStack()));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endSection(java.util.Map)
+ */
+ public void endSection(Map parameters) {
+ this.stack.push(new SectionBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endTable(java.util.Map)
+ */
+ public void endTable(Map parameters) {
+ this.stack.push(new TableBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map)
+ */
+ public void endTableCell(Map parameters) {
+ this.stack.push(new TableCellBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map)
+ */
+ public void endTableHeadCell(Map parameters) {
+ this.stack.push(new TableHeadCellBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#endTableRow(java.util.Map)
+ */
+ public void endTableRow(Map parameters) {
+ this.stack.push(new TableRowBlock(generateListFromStack(), parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.LinkListener#endLink(org.xwiki.rendering.listener.reference.ResourceReference
+ * ,
+ * boolean, java.util.Map)
+ */
+ public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ this.stack.push(new LinkBlock(generateListFromStack(), reference, isFreeStandingURI, parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onEmptyLines(int)
+ */
+ public void onEmptyLines(int count) {
+ this.stack.push(new EmptyLinesBlock(count));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onHorizontalLine(java.util.Map)
+ */
+ public void onHorizontalLine(Map parameters) {
+ this.stack.push(new HorizontalLineBlock(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onId(java.lang.String)
+ */
+ public void onId(String name) {
+ this.stack.push(new IdBlock(name));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onMacro(java.lang.String, java.util.Map,
+ * java.lang.String, boolean)
+ */
+ public void onMacro(String id, Map macroParameters, String content, boolean isInline) {
+ this.stack.push(new MacroBlock(id, macroParameters, content, isInline));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onNewLine()
+ */
+ public void onNewLine() {
+ this.stack.push(new NewLineBlock());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onRawText(java.lang.String,
+ * org.xwiki.rendering.syntax.Syntax)
+ */
+ public void onRawText(String rawContent, Syntax syntax) {
+ this.stack.push(new RawBlock(rawContent, syntax));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onSpace()
+ */
+ public void onSpace() {
+ this.stack.push(new SpaceBlock());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onSpecialSymbol(char)
+ */
+ public void onSpecialSymbol(char symbol) {
+ this.stack.push(new SpecialSymbolBlock(symbol));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onVerbatim(java.lang.String, boolean, java.util.Map)
+ */
+ public void onVerbatim(String protectedString, boolean isInline, Map parameters) {
+ this.stack.push(new VerbatimBlock(protectedString, parameters, isInline));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#onWord(java.lang.String)
+ */
+ public void onWord(String word) {
+ this.stack.push(new WordBlock(word));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.ImageListener#onImage(org.xwiki.rendering.listener.reference.ResourceReference
+ * , boolean, java.util.Map)
+ */
+ public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ this.stack.push(new ImageBlock(reference, isFreeStandingURI, parameters));
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/AbstractURIResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/AbstractURIResourceReferenceTypeParser.java
new file mode 100644
index 000000000..4be0698ae
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/AbstractURIResourceReferenceTypeParser.java
@@ -0,0 +1,43 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.parser.ResourceReferenceTypeParser;
+
+/**
+ * Default resource reference type parser for URIs: just take the full reference as the Resource
+ * reference. Note that
+ * this parser doesn't extract the scheme from the URI for the resource reference.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+public abstract class AbstractURIResourceReferenceTypeParser implements ResourceReferenceTypeParser {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.parser.ResourceReferenceTypeParser#parse(String)
+ */
+ public ResourceReference parse(String reference) {
+ return new ResourceReference(reference, getType());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/AttachmentResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/AttachmentResourceReferenceTypeParser.java
new file mode 100644
index 000000000..a5dabc037
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/AttachmentResourceReferenceTypeParser.java
@@ -0,0 +1,42 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceType;
+
+/**
+ * Parses a resource reference to an attachment.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("attach")
+public class AttachmentResourceReferenceTypeParser extends AbstractURIResourceReferenceTypeParser {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#getType()
+ */
+ public ResourceType getType() {
+ return ResourceType.ATTACHMENT;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultImageReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultImageReferenceParser.java
new file mode 100644
index 000000000..f0fb26eb1
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultImageReferenceParser.java
@@ -0,0 +1,65 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+import org.xwiki.rendering.parser.ResourceReferenceParser;
+
+/**
+ * Similar to {@link org.xwiki.rendering.internal.parser.reference.DefaultResourceReferenceParser}
+ * but handles the case
+ * where the resource type wasn't specified. In this case it tries to guess the type by first
+ * looking for a URL and then
+ * considering it's a reference to an attachment.
+ *
+ * @version $Id$
+ * @since 2.6M1
+ */
+@Component("image")
+public class DefaultImageReferenceParser implements ResourceReferenceParser {
+
+ /**
+ * Default parser to parse typed resource references.
+ */
+ @Requirement
+ private ResourceReferenceParser defaultResourceReferenceParser;
+
+ /**
+ * Used to parse untyped resource reference and guess their types.
+ */
+ @Requirement("image/untyped")
+ private ResourceReferenceParser untypedImageReferenceParser;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see ResourceReferenceParser#parse(String)
+ */
+ public ResourceReference parse(String rawReference) {
+ ResourceReference reference = this.defaultResourceReferenceParser.parse(rawReference);
+ if (reference.getType().equals(ResourceType.UNKNOWN)) {
+ reference = this.untypedImageReferenceParser.parse(rawReference);
+ }
+ return reference;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultLinkReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultLinkReferenceParser.java
new file mode 100644
index 000000000..66c60b112
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultLinkReferenceParser.java
@@ -0,0 +1,65 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+import org.xwiki.rendering.parser.ResourceReferenceParser;
+
+/**
+ * Similar to {@link org.xwiki.rendering.internal.parser.reference.DefaultResourceReferenceParser}
+ * but handles the case
+ * where the resource type wasn't specified. In this case it tries to guess the type by first
+ * looking for a URL and then
+ * considering it's a reference to a document.
+ *
+ * @version $Id$
+ * @since 2.6M1
+ */
+@Component("link")
+public class DefaultLinkReferenceParser implements ResourceReferenceParser {
+
+ /**
+ * Default parser to parse typed resource references.
+ */
+ @Requirement
+ private ResourceReferenceParser defaultResourceReferenceParser;
+
+ /**
+ * Used to parse untyped resource reference and guess their types.
+ */
+ @Requirement("link/untyped")
+ private ResourceReferenceParser untypedLinkReferenceParser;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see ResourceReferenceParser#parse(String)
+ */
+ public ResourceReference parse(String rawReference) {
+ ResourceReference reference = this.defaultResourceReferenceParser.parse(rawReference);
+ if (reference.getType().equals(ResourceType.UNKNOWN)) {
+ reference = this.untypedLinkReferenceParser.parse(rawReference);
+ }
+ return reference;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultResourceReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultResourceReferenceParser.java
new file mode 100644
index 000000000..c237bb36a
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultResourceReferenceParser.java
@@ -0,0 +1,115 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentManager;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+import org.xwiki.rendering.parser.ResourceReferenceParser;
+import org.xwiki.rendering.parser.ResourceReferenceTypeParser;
+import org.xwiki.rendering.wiki.WikiModel;
+
+/**
+ * Parses the content of resource references. The format of a resource reference is the following:
+ * {@code (type):(reference)} where {@code type} represents the type (see
+ * {@link org.xwiki.rendering.listener.reference.ResourceType} of the resource pointed to (e.g.
+ * document, mailto,
+ * attachment, image, document in another wiki, etc), and {@code reference} defines the target. The
+ * syntax of
+ * {@code reference} depends on the Resource type and is documented in the javadoc of the various
+ * {@link org.xwiki.rendering.parser.ResourceReferenceTypeParser} implementations. Note that the
+ * implementation is
+ * pluggable and it's allowed plug new resource reference types by implementing
+ * {@link org.xwiki.rendering.parser.ResourceReferenceTypeParser}s and registering the
+ * implementation as a component.
+ *
+ * @version $Id$
+ * @since 2.6M1
+ */
+@Component
+public class DefaultResourceReferenceParser implements ResourceReferenceParser {
+
+ /**
+ * Link Reference Type separator (eg "mailto:mail@address").
+ */
+ public static final String TYPE_SEPARATOR = ":";
+
+ /**
+ * Used to verify if we're in wiki mode or not by looking up an implementation of
+ * {@link org.xwiki.rendering.wiki.WikiModel}.
+ */
+ @Requirement
+ private ComponentManager componentManager;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the parsed resource reference or a Resource Reference with {@link ResourceType#UNKNOWN}
+ * if no reference
+ * type was specified
+ * @see org.xwiki.rendering.parser.ResourceReferenceParser#parse(String)
+ */
+ public ResourceReference parse(String rawReference) {
+ // Step 1: If we're not in wiki mode then all links are URL links.
+ if (!isInWikiMode()) {
+ ResourceReference resourceReference = new ResourceReference(rawReference, ResourceType.URL);
+ resourceReference.setTyped(false);
+ return resourceReference;
+ }
+
+ // Step 2: Find the type parser matching the specified prefix type (if any).
+ int pos = rawReference.indexOf(TYPE_SEPARATOR);
+ if (pos > -1) {
+ String typePrefix = rawReference.substring(0, pos);
+ String reference = rawReference.substring(pos + 1);
+ try {
+ ResourceReferenceTypeParser parser = this.componentManager.lookup(ResourceReferenceTypeParser.class,
+ typePrefix);
+ ResourceReference parsedResourceReference = parser.parse(reference);
+ if (parsedResourceReference != null) {
+ return parsedResourceReference;
+ }
+ } catch (ComponentLookupException e) {
+ // Couldn't find a link type parser for the specified type. Will try to autodiscover the
+ // type.
+ }
+ }
+
+ // Step 3: There's no specific type parser found.
+ return new ResourceReference(rawReference, ResourceType.UNKNOWN);
+ }
+
+ /**
+ * @return true if we're in wiki mode (ie there's no implementing class for
+ * {@link org.xwiki.rendering.wiki.WikiModel})
+ */
+ private boolean isInWikiMode() {
+ boolean result = true;
+ try {
+ this.componentManager.lookup(WikiModel.class);
+ } catch (ComponentLookupException e) {
+ result = false;
+ }
+ return result;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultUntypedImageReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultUntypedImageReferenceParser.java
new file mode 100644
index 000000000..4fac8eb83
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultUntypedImageReferenceParser.java
@@ -0,0 +1,70 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.parser.ResourceReferenceParser;
+import org.xwiki.rendering.parser.ResourceReferenceTypeParser;
+
+/**
+ * Considers all passed images references to be untyped and tries to guess the type by first looking
+ * for a URL and then
+ * considering it's a reference to an attachment.
+ *
+ * @version $Id$
+ * @since 2.6M1
+ */
+@Component("image/untyped")
+public class DefaultUntypedImageReferenceParser implements ResourceReferenceParser {
+
+ /**
+ * Parser to parse link references pointing to URLs.
+ */
+ @Requirement("url")
+ private ResourceReferenceTypeParser urlResourceReferenceTypeParser;
+
+ /**
+ * Parser to parse link references pointing to attachments.
+ */
+ @Requirement("attach")
+ private ResourceReferenceTypeParser attachmentResourceReferenceTypeParser;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see ResourceReferenceParser#parse(String)
+ */
+ public ResourceReference parse(String rawReference) {
+ // Try to guess the link type. It can be either:
+ // - a URL (specified without the "url" type)
+ // - a reference to an attachment (specified without the "attach" type)
+ ResourceReference reference = this.urlResourceReferenceTypeParser.parse(rawReference);
+ if (reference == null) {
+ // What remains is considered to be a link to an attachment, use the attachment link type
+ // parser to
+ // parse.
+ reference = this.attachmentResourceReferenceTypeParser.parse(rawReference);
+ }
+ reference.setTyped(false);
+ return reference;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultUntypedLinkReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultUntypedLinkReferenceParser.java
new file mode 100644
index 000000000..00ed422fb
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DefaultUntypedLinkReferenceParser.java
@@ -0,0 +1,70 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.parser.ResourceReferenceParser;
+import org.xwiki.rendering.parser.ResourceReferenceTypeParser;
+
+/**
+ * Considers all passed link references to be untyped and tries to guess the type by first looking
+ * for a URL and then
+ * considering it's a reference to a document.
+ *
+ * @version $Id$
+ * @since 2.6M1
+ */
+@Component("link/untyped")
+public class DefaultUntypedLinkReferenceParser implements ResourceReferenceParser {
+
+ /**
+ * Parser to parse link references pointing to URLs.
+ */
+ @Requirement("url")
+ private ResourceReferenceTypeParser urlResourceReferenceTypeParser;
+
+ /**
+ * Parser to parse link references pointing to documents.
+ */
+ @Requirement("doc")
+ private ResourceReferenceTypeParser documentResourceReferenceTypeParser;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see ResourceReferenceParser#parse(String)
+ */
+ public ResourceReference parse(String rawReference) {
+ // Try to guess the link type. It can be either:
+ // - a URL (specified without the "url" type)
+ // - a reference to a document (specified without the "doc" type)
+ ResourceReference reference = this.urlResourceReferenceTypeParser.parse(rawReference);
+ if (reference == null) {
+ // What remains is considered to be a link to a document, use the document link type parser to
+ // parse it.
+ reference = this.documentResourceReferenceTypeParser.parse(rawReference);
+ }
+ reference.setTyped(false);
+
+ return reference;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DocumentResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DocumentResourceReferenceTypeParser.java
new file mode 100644
index 000000000..308368d07
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/DocumentResourceReferenceTypeParser.java
@@ -0,0 +1,58 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.DocumentResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+
+/**
+ * Parses a resource reference to a document.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("doc")
+public class DocumentResourceReferenceTypeParser extends AbstractURIResourceReferenceTypeParser {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#getType()
+ */
+ public ResourceType getType() {
+ return ResourceType.DOCUMENT;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#parse(String)
+ */
+ @Override
+ public ResourceReference parse(String reference) {
+ // Note that we construct a DocumentResourceReference object so that the user who calls
+ // {@link ResourceReferenceParser#parse} can cast it to a DocumentResourceReference object if
+ // the type is of
+ // type Document.
+ return new DocumentResourceReference(reference);
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/GenericImageReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/GenericImageReferenceParser.java
new file mode 100644
index 000000000..2a0dde4be
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/GenericImageReferenceParser.java
@@ -0,0 +1,33 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+
+/**
+ * Each syntax should have its own resource reference parser. However while we wait for syntax
+ * specific parser to be
+ * implemented this generic parser should provide a good approximation.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("default/image")
+public class GenericImageReferenceParser extends XWiki20ImageReferenceParser {}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/GenericLinkReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/GenericLinkReferenceParser.java
new file mode 100644
index 000000000..3c41f0697
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/GenericLinkReferenceParser.java
@@ -0,0 +1,51 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.xwiki.component.annotation.Component;
+
+/**
+ * Each syntax should have its own resource reference parser. However while we wait for syntax
+ * specific parser to be
+ * implemented this generic parser should provide a good approximation.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("default/link")
+public class GenericLinkReferenceParser extends XWiki20LinkReferenceParser {
+
+ /**
+ * The list of recognized URL prefixes.
+ */
+ private static final List URI_PREFIXES = Arrays.asList("mailto");
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see XWiki20LinkReferenceParser#getAllowedURIPrefixes()
+ */
+ protected List getAllowedURIPrefixes() {
+ return URI_PREFIXES;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/IconResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/IconResourceReferenceTypeParser.java
new file mode 100644
index 000000000..c75f5b655
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/IconResourceReferenceTypeParser.java
@@ -0,0 +1,42 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceType;
+
+/**
+ * Parses a resource reference to an icon.
+ *
+ * @version $Id$
+ * @since 2.6M1
+ */
+@Component("icon")
+public class IconResourceReferenceTypeParser extends AbstractURIResourceReferenceTypeParser {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.internal.parser.reference.AbstractURIResourceReferenceTypeParser#getType()
+ */
+ public ResourceType getType() {
+ return ResourceType.ICON;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/InterWikiResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/InterWikiResourceReferenceTypeParser.java
new file mode 100644
index 000000000..ee33f8a59
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/InterWikiResourceReferenceTypeParser.java
@@ -0,0 +1,72 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.InterWikiResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+
+/**
+ * Parses a resource reference to a document in another wiki (interwiki).
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("interwiki")
+public class InterWikiResourceReferenceTypeParser extends AbstractURIResourceReferenceTypeParser {
+
+ /**
+ * Separator between the interwiki alias and the interwiki path (eg "alias" in
+ * interwiki:alias:path).
+ */
+ public static final String INTERWIKI_ALIAS_SEPARATOR = ":";
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#getType()
+ */
+ public ResourceType getType() {
+ return ResourceType.INTERWIKI;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#parse(String)
+ */
+ @Override
+ public ResourceReference parse(String reference) {
+ ResourceReference resultReference = null;
+ // Try to find an interwiki separator to extract the interwiki alias from the interwiki suffix.
+ // If no separator is found it means the interwiki link syntax is invalid. In this case consider
+ // that the
+ // reference is not an interwiki link.
+ int pos = reference.indexOf(INTERWIKI_ALIAS_SEPARATOR);
+ if (pos > -1) {
+ InterWikiResourceReference interWikiReference = new InterWikiResourceReference(
+ reference.substring(pos + INTERWIKI_ALIAS_SEPARATOR.length()));
+ interWikiReference.setInterWikiAlias(reference.substring(0, pos + INTERWIKI_ALIAS_SEPARATOR.length() - 1));
+ resultReference = interWikiReference;
+ }
+ return resultReference;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/MailtoResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/MailtoResourceReferenceTypeParser.java
new file mode 100644
index 000000000..7cc0a534b
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/MailtoResourceReferenceTypeParser.java
@@ -0,0 +1,42 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceType;
+
+/**
+ * Parses a resource reference to a mail.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("mailto")
+public class MailtoResourceReferenceTypeParser extends AbstractURIResourceReferenceTypeParser {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#getType()
+ */
+ public ResourceType getType() {
+ return ResourceType.MAILTO;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/PathResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/PathResourceReferenceTypeParser.java
new file mode 100644
index 000000000..49832ad83
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/PathResourceReferenceTypeParser.java
@@ -0,0 +1,42 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceType;
+
+/**
+ * Parses a resource reference to a relative URL.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("path")
+public class PathResourceReferenceTypeParser extends AbstractURIResourceReferenceTypeParser {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#getType()
+ */
+ public ResourceType getType() {
+ return ResourceType.PATH;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/UNCResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/UNCResourceReferenceTypeParser.java
new file mode 100644
index 000000000..8da40e355
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/UNCResourceReferenceTypeParser.java
@@ -0,0 +1,42 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceType;
+
+/**
+ * Parses a resource reference to a UNC (Universal Naming Convention).
+ *
+ * @version $Id$
+ * @since 2.7M1
+ */
+@Component("unc")
+public class UNCResourceReferenceTypeParser extends AbstractURIResourceReferenceTypeParser {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#getType()
+ */
+ public ResourceType getType() {
+ return ResourceType.UNC;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/URLResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/URLResourceReferenceTypeParser.java
new file mode 100644
index 000000000..e3d6185a1
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/URLResourceReferenceTypeParser.java
@@ -0,0 +1,69 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+
+/**
+ * Parses a resource reference to a URL.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("url")
+public class URLResourceReferenceTypeParser extends AbstractURIResourceReferenceTypeParser {
+
+ /**
+ * URL matching pattern.
+ */
+ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("[a-zA-Z0-9+.-]*://");
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#getType()
+ */
+ public ResourceType getType() {
+ return ResourceType.URL;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractURIResourceReferenceTypeParser#parse(String)
+ */
+ @Override
+ public ResourceReference parse(String reference) {
+ ResourceReference resultReference = null;
+ Matcher matcher = URL_SCHEME_PATTERN.matcher(reference);
+ if (matcher.lookingAt()) {
+ // We don't parse the URL since it can contain unknown protocol for the JVM but protocols
+ // known by the
+ // browser (such as skype:// for example).
+ resultReference = new ResourceReference(reference, getType());
+ }
+ return resultReference;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/XWiki20ImageReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/XWiki20ImageReferenceParser.java
new file mode 100644
index 000000000..7996b588e
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/XWiki20ImageReferenceParser.java
@@ -0,0 +1,75 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentManager;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+import org.xwiki.rendering.parser.ResourceReferenceParser;
+import org.xwiki.rendering.wiki.WikiModel;
+
+/**
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("xwiki/2.0/image")
+public class XWiki20ImageReferenceParser implements ResourceReferenceParser {
+
+ /**
+ * Used to verify if we're in wiki mode or not by looking up an implementation of
+ * {@link org.xwiki.rendering.wiki.WikiModel}. In non wiki mode all image references are
+ * considered as URLs.
+ */
+ @Requirement
+ private ComponentManager componentManager;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.parser.ResourceReferenceParser#parse(String)
+ */
+ public ResourceReference parse(String rawReference) {
+ ResourceType type;
+ if (rawReference.startsWith("http://") || !isInWikiMode()) {
+ type = ResourceType.URL;
+ } else {
+ type = ResourceType.ATTACHMENT;
+ }
+ ResourceReference result = new ResourceReference(rawReference, type);
+ result.setTyped(false);
+ return result;
+ }
+
+ /**
+ * @return true if we're in wiki mode (ie there's no implementing class for {@link WikiModel})
+ */
+ private boolean isInWikiMode() {
+ boolean result = true;
+ try {
+ this.componentManager.lookup(WikiModel.class);
+ } catch (ComponentLookupException e) {
+ result = false;
+ }
+ return result;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/XWiki20LinkReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/XWiki20LinkReferenceParser.java
new file mode 100644
index 000000000..b1b96ccfb
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/reference/XWiki20LinkReferenceParser.java
@@ -0,0 +1,377 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.parser.reference;
+
+import org.apache.commons.lang.StringUtils;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentManager;
+import org.xwiki.rendering.listener.reference.DocumentResourceReference;
+import org.xwiki.rendering.listener.reference.InterWikiResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+import org.xwiki.rendering.parser.ResourceReferenceParser;
+import org.xwiki.rendering.parser.ResourceReferenceTypeParser;
+import org.xwiki.rendering.wiki.WikiModel;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Parses the content of XWiki 2.0 resource references. The supported generic format is as follows:
+ * (link)(@interWikiAlias)?, where:
+ *
+ * link: The full link reference using the following syntax:
+ * (reference)(#anchor)?(?queryString)?, where:
+ *
+ * reference: The link reference. This can be either a URI in the form
+ * protocol:path
+ * (example: "http://xwiki.org", "mailto:john@smith.com) or a wiki page name (example:
+ * "wiki:Space.WebHome"). Note that
+ * in the case of a wiki page name the character "\" is used as the escape character (for example if
+ * you wish to have
+ * "#" or "?" in your page name you'll need to write "\#" and "\?").
+ * anchor: An optional anchor name pointing to an anchor defined in the referenced
+ * link. Note that in
+ * XWiki anchors are automatically created for titles. Example: "TableOfContentAnchor".
+ * queryString: An optional query string for specifying parameters that will be
+ * used in the rendered
+ * URL. Example: "mydata1=5&mydata2=Hello".
+ *
+ * The link element is mandatory.
+ * interWikiAlias: An optional
+ * Inter Wiki alias as
+ * defined in the InterWiki Map. Example: "wikipedia"
+ *
+ * Examples of valid wiki links:
+ *
+ * - Hello World
+ * - http://myserver.com/HelloWorld
+ * - HelloWorld#Anchor
+ * - Hello World@Wikipedia
+ * - mywiki:HelloWorld
+ * - Hello World?param1=1¶m2=2
+ *
+ * Note that allowed URIs are URLs of the form {@code http://}, {@code mailto:}, {@code image:} and
+ * {@code attach:}.
+ *
+ * @version $Id$
+ * @since 2.5RC1
+ */
+@Component("xwiki/2.0/link")
+public class XWiki20LinkReferenceParser implements ResourceReferenceParser {
+
+ /**
+ * Interwiki separator.
+ */
+ public static final String SEPARATOR_INTERWIKI = "@";
+
+ /**
+ * Query String separator.
+ */
+ public static final String SEPARATOR_QUERYSTRING = "?";
+
+ /**
+ * Anchor separator.
+ */
+ public static final String SEPARATOR_ANCHOR = "#";
+
+ /**
+ * Escape character to allow "#", "@" and "?" characters in a reference's name.
+ */
+ public static final char ESCAPE_CHAR = '\\';
+
+ /**
+ * Escapes to remove from the document reference part when parsing the raw reference (i.e.
+ * excluding query string,
+ * anchor and interwiki parts). Note that we don't remove the escaped escape char since this is
+ * how an escape char
+ * is represented in an Entity Reference.
+ */
+ private static final String[] ESCAPES_REFERENCE = new String[] { ESCAPE_CHAR + SEPARATOR_QUERYSTRING,
+ ESCAPE_CHAR + SEPARATOR_INTERWIKI, ESCAPE_CHAR + SEPARATOR_ANCHOR };
+
+ /**
+ * Escapes to remove from the query string, anchor and interwiki parts when parsing the raw
+ * reference.
+ */
+ private static final String[] ESCAPES_EXTRA = new String[] { ESCAPE_CHAR + SEPARATOR_QUERYSTRING,
+ ESCAPE_CHAR + SEPARATOR_INTERWIKI, ESCAPE_CHAR + SEPARATOR_ANCHOR, "" + ESCAPE_CHAR + ESCAPE_CHAR };
+
+ /**
+ * Escapes to remove the interwiki content.
+ */
+ private static final String[] ESCAPE_INTERWIKI = new String[] { "" + ESCAPE_CHAR + ESCAPE_CHAR, "" + ESCAPE_CHAR };
+
+ /**
+ * Replacement chars for the escapes to be removed from the reference part.
+ */
+ private static final String[] ESCAPE_REPLACEMENTS_REFERENCE = new String[] { SEPARATOR_QUERYSTRING,
+ SEPARATOR_INTERWIKI, SEPARATOR_ANCHOR };
+
+ /**
+ * Replacement chars for the escapes to be removed from the query string, anchor and interwiki
+ * parts.
+ */
+ private static final String[] ESCAPE_REPLACEMENTS_EXTRA = new String[] { SEPARATOR_QUERYSTRING, SEPARATOR_INTERWIKI,
+ SEPARATOR_ANCHOR, "" + ESCAPE_CHAR };
+
+ /**
+ * Replacements chars for the escapes to be removed from the interwiki content.
+ */
+ private static final String[] ESCAPE_REPLACEMENTS_INTERWIKI = new String[] { "" + ESCAPE_CHAR, "" };
+
+ /**
+ * The list of recognized URL prefixes.
+ */
+ private static final List URI_PREFIXES = Arrays.asList("mailto", "image", "attach");
+
+ /**
+ * Parser to parse link references pointing to URLs.
+ */
+ @Requirement("url")
+ private ResourceReferenceTypeParser urlResourceReferenceTypeParser;
+
+ /**
+ * Used to verify if we're in wiki mode or not by looking up an implementation of
+ * {@link org.xwiki.rendering.wiki.WikiModel}.
+ */
+ @Requirement
+ private ComponentManager componentManager;
+
+ /**
+ * @return the list of URI prefixes the link parser recognizes
+ */
+ protected List getAllowedURIPrefixes() {
+ return URI_PREFIXES;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.parser.ResourceReferenceParser#parse(java.lang.String)
+ */
+ public ResourceReference parse(String rawReference) {
+ // Step 1: If we're not in wiki mode then all links are URL links.
+ if (!isInWikiMode()) {
+ ResourceReference resourceReference = new ResourceReference(rawReference, ResourceType.URL);
+ resourceReference.setTyped(false);
+ return resourceReference;
+ }
+
+ // Step 2: Check if it's a known URI by looking for one of the known URI schemes. If not, check
+ // if it's a URL.
+ ResourceReference resourceReference = parseURILinks(rawReference);
+ if (resourceReference != null) {
+ return resourceReference;
+ }
+
+ // Step 3: Look for an InterWiki link
+ StringBuffer content = new StringBuffer(rawReference);
+ resourceReference = parseInterWikiLinks(content);
+ if (resourceReference != null) {
+ return resourceReference;
+ }
+
+ // Step 4: Consider that we have a reference to a document.
+ return parseDocumentLink(content);
+ }
+
+ /**
+ * Construct a Document Link reference out of the passed content.
+ *
+ * @param content
+ * the string containing the Document link reference
+ * @return the parsed Link Object corresponding to the Document link reference
+ */
+ private ResourceReference parseDocumentLink(StringBuffer content) {
+ String queryString = null;
+ String text = parseElementAfterString(content, SEPARATOR_QUERYSTRING);
+ if (text != null) {
+ queryString = removeEscapesFromExtraParts(text);
+ }
+
+ String anchor = null;
+ text = parseElementAfterString(content, SEPARATOR_ANCHOR);
+ if (text != null) {
+ anchor = removeEscapesFromExtraParts(text);
+ }
+
+ DocumentResourceReference reference = new DocumentResourceReference(
+ removeEscapesFromReferencePart(content.toString()));
+ reference.setTyped(false);
+ reference.setQueryString(queryString);
+ reference.setAnchor(anchor);
+
+ return reference;
+ }
+
+ /**
+ * Check if the passed link references is an URI link reference.
+ *
+ * @param rawLink
+ * the original reference to parse
+ * @return the parsed Link object or null if the passed reference is not an URI link reference or
+ * if no URI type
+ * parser was found for the passed URI scheme
+ */
+ private ResourceReference parseURILinks(String rawLink) {
+ ResourceReference result = null;
+ int uriSchemeDelimiterPos = rawLink.indexOf(":");
+ if (uriSchemeDelimiterPos > -1) {
+ String scheme = rawLink.substring(0, uriSchemeDelimiterPos);
+ String reference = rawLink.substring(uriSchemeDelimiterPos + 1);
+ if (getAllowedURIPrefixes().contains(scheme)) {
+ try {
+ ResourceReference resourceReference = this.componentManager
+ .lookup(ResourceReferenceTypeParser.class, scheme).parse(reference);
+ if (resourceReference != null) {
+ result = resourceReference;
+ }
+ } catch (ComponentLookupException e) {
+ // Failed to lookup component, this shouldn't happen but ignore it.
+ }
+ } else {
+ // Check if it's a URL
+ ResourceReference resourceReference = this.urlResourceReferenceTypeParser.parse(rawLink);
+ if (resourceReference != null) {
+ resourceReference.setTyped(false);
+ result = resourceReference;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Check if the passed link references is an interwiki link reference.
+ *
+ * @param content
+ * the original content to parse
+ * @return the parsed Link object or null if the passed reference is not an interwiki link
+ * reference
+ */
+ private ResourceReference parseInterWikiLinks(StringBuffer content) {
+ ResourceReference result = null;
+ String interWikiAlias = parseElementAfterString(content, SEPARATOR_INTERWIKI);
+ if (interWikiAlias != null) {
+ InterWikiResourceReference link = new InterWikiResourceReference(removeEscapes(content.toString()));
+ link.setInterWikiAlias(removeEscapes(interWikiAlias));
+ result = link;
+ }
+ return result;
+ }
+
+ /**
+ * Find out the element located to the right of the passed separator.
+ *
+ * @param content
+ * the string to parse. This parameter will be modified by the method to remove the
+ * parsed content.
+ * @param separator
+ * the separator string to locate the element
+ * @return the parsed element or null if the separator string wasn't found
+ */
+ protected String parseElementAfterString(StringBuffer content, String separator) {
+ String element = null;
+
+ // Find the first non escaped separator (starting from the end of the content buffer).
+ int index = content.lastIndexOf(separator);
+ while (index != -1) {
+ // Check if the element is found and it's not escaped.
+ if (!shouldEscape(content, index)) {
+ element = content.substring(index + separator.length()).trim();
+ content.delete(index, content.length());
+ break;
+ }
+
+ if (index > 0) {
+ index = content.lastIndexOf(separator, index - 1);
+ } else {
+ break;
+ }
+ }
+
+ return element;
+ }
+
+ /**
+ * @return true if we're in wiki mode (ie there's no implementing class for
+ * {@link org.xwiki.rendering.wiki.WikiModel})
+ */
+ private boolean isInWikiMode() {
+ boolean result = true;
+ try {
+ this.componentManager.lookup(WikiModel.class);
+ } catch (ComponentLookupException e) {
+ result = false;
+ }
+ return result;
+ }
+
+ /**
+ * Count the number of escape chars before a given character and if that number is odd then that
+ * character should be
+ * escaped.
+ *
+ * @param content
+ * the content in which to check for escapes
+ * @param charPosition
+ * the position of the char for which to decide if it should be escaped or not
+ * @return true if the character should be escaped
+ */
+ private boolean shouldEscape(StringBuffer content, int charPosition) {
+ int counter = 0;
+ int pos = charPosition - 1;
+ while (pos > -1 && content.charAt(pos) == ESCAPE_CHAR) {
+ counter++;
+ pos--;
+ }
+ return (counter % 2 != 0);
+ }
+
+ /**
+ * @param text
+ * the reference from which to remove unneeded escapes
+ * @return the cleaned text
+ */
+ private String removeEscapesFromReferencePart(String text) {
+ return StringUtils.replaceEach(text, ESCAPES_REFERENCE, ESCAPE_REPLACEMENTS_REFERENCE);
+ }
+
+ /**
+ * @param text
+ * the reference from which to remove unneeded escapes
+ * @return the cleaned text
+ */
+ private String removeEscapesFromExtraParts(String text) {
+ return StringUtils.replaceEach(text, ESCAPES_EXTRA, ESCAPE_REPLACEMENTS_EXTRA);
+ }
+
+ /**
+ * @param text
+ * the reference from which to remove unneeded escapes
+ * @return the cleaned text
+ */
+ private String removeEscapes(String text) {
+ return StringUtils.replaceEach(text, ESCAPE_INTERWIKI, ESCAPE_REPLACEMENTS_INTERWIKI);
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractBlockRenderer.java
new file mode 100644
index 000000000..bf698e30b
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractBlockRenderer.java
@@ -0,0 +1,65 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer;
+
+import java.util.Collection;
+import java.util.Collections;
+import org.xwiki.rendering.block.Block;
+import org.xwiki.rendering.renderer.BlockRenderer;
+import org.xwiki.rendering.renderer.PrintRendererFactory;
+import org.xwiki.rendering.renderer.printer.WikiPrinter;
+import org.xwiki.rendering.renderer.PrintRenderer;
+
+/**
+ * Common code for BlockRender implementation that uses Print Renderer Factory.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+public abstract class AbstractBlockRenderer implements BlockRenderer {
+
+ /**
+ * @return provide the factory to use to create a new {@link PrintRenderer}.
+ */
+ protected abstract PrintRendererFactory getPrintRendererFactory();
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see BlockRenderer#render(org.xwiki.rendering.block.Block,
+ * org.xwiki.rendering.renderer.printer.WikiPrinter)
+ */
+ public void render(Block block, WikiPrinter printer) {
+ render(Collections.singletonList(block), printer);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see BlockRenderer#render(java.util.Collection,
+ * org.xwiki.rendering.renderer.printer.WikiPrinter)
+ */
+ public void render(Collection blocks, WikiPrinter printer) {
+ PrintRenderer renderer = getPrintRendererFactory().createRenderer(printer);
+ for (Block block : blocks) {
+ block.traverse(renderer);
+ }
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractPrintRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractPrintRendererFactory.java
new file mode 100644
index 000000000..37d4b5566
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractPrintRendererFactory.java
@@ -0,0 +1,62 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer;
+
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentManager;
+import org.xwiki.rendering.renderer.PrintRenderer;
+import org.xwiki.rendering.renderer.PrintRendererFactory;
+import org.xwiki.rendering.renderer.printer.WikiPrinter;
+
+/**
+ * Common code for {@link org.xwiki.rendering.renderer.PrintRendererFactory}, implements the logic
+ * to lookup and call
+ * the matching Print Renderer.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+public abstract class AbstractPrintRendererFactory implements PrintRendererFactory {
+
+ /**
+ * Used to lookup the {@link PrintRenderer}.
+ */
+ @Requirement
+ private ComponentManager componentManager;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see PrintRendererFactory#createRenderer(org.xwiki.rendering.renderer.printer.WikiPrinter)
+ */
+ public PrintRenderer createRenderer(WikiPrinter printer) {
+ PrintRenderer renderer;
+ try {
+ renderer = this.componentManager.lookup(PrintRenderer.class, getSyntax().toIdString());
+ } catch (ComponentLookupException e) {
+ throw new RuntimeException("Failed to create [" + getSyntax().toString() + "] renderer", e);
+ }
+
+ renderer.setPrinter(printer);
+
+ return renderer;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultAttachmentURILabelGenerator.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultAttachmentURILabelGenerator.java
new file mode 100644
index 000000000..d5260a675
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultAttachmentURILabelGenerator.java
@@ -0,0 +1,44 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.renderer.reference.link.URILabelGenerator;
+
+/**
+ * Generate link labels for ATTACH URIs.
+ *
+ * @version $Id: DefaultAttachmentURILabelGenerator.java 31386 2010-09-27 09:42:32Z vmassol $
+ * @since 2.5RC1
+ */
+@Component("attach")
+public class DefaultAttachmentURILabelGenerator implements URILabelGenerator {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.reference.link.URILabelGenerator#generateLabel(
+ * org.xwiki.rendering.listener.reference.ResourceReference)
+ */
+ public String generateLabel(ResourceReference reference) {
+ return reference.getReference();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultLinkLabelGenerator.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultLinkLabelGenerator.java
new file mode 100644
index 000000000..a9b0359f6
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultLinkLabelGenerator.java
@@ -0,0 +1,46 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator;
+
+/**
+ * Basic default implementation to be used when the XWiki Rendering is used standalone, outside of
+ * XWiki.
+ *
+ * @version $Id$
+ * @since 2.0M1
+ */
+@Component
+public class DefaultLinkLabelGenerator implements LinkLabelGenerator {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator#generate(
+ * org.xwiki.rendering.listener.reference.ResourceReference)
+ * @since 2.5RC1
+ */
+ public String generate(ResourceReference reference) {
+ return reference.getReference();
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/MailtoURILabelGenerator.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/MailtoURILabelGenerator.java
new file mode 100644
index 000000000..953b7ea30
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/MailtoURILabelGenerator.java
@@ -0,0 +1,46 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer;
+
+import org.apache.commons.lang.StringUtils;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.renderer.reference.link.URILabelGenerator;
+
+/**
+ * Generate link labels for MAILTO URIs.
+ *
+ * @version $Id$
+ * @since 2.2RC1
+ */
+@Component("mailto")
+public class MailtoURILabelGenerator implements URILabelGenerator {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.reference.link.URILabelGenerator#generateLabel(
+ * org.xwiki.rendering.listener.reference.ResourceReference)
+ */
+ public String generateLabel(ResourceReference reference) {
+ // Remove the query string (if any).
+ return StringUtils.substringBefore(reference.getReference(), "?");
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/ParametersPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/ParametersPrinter.java
new file mode 100644
index 000000000..747e3bc02
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/ParametersPrinter.java
@@ -0,0 +1,82 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer;
+
+import java.util.Map;
+
+/**
+ * Generates syntax for a parameters group like macros and links.
+ *
+ * @version $Id$
+ * @since 1.9RC2
+ */
+public class ParametersPrinter {
+
+ /**
+ * Quote character.
+ */
+ private static final String QUOTE = "\"";
+
+ /**
+ * Print the parameters as a String.
+ *
+ * @param parameters
+ * the parameters to print
+ * @param escapeChar
+ * the character used in front of a special character when need to escape it
+ * @return the printed parameters
+ */
+ public String print(Map parameters, char escapeChar) {
+ StringBuffer buffer = new StringBuffer();
+ for (Map.Entry entry : parameters.entrySet()) {
+ String value = entry.getValue();
+ String key = entry.getKey();
+
+ if (key != null && value != null) {
+ if (buffer.length() > 0) {
+ buffer.append(' ');
+ }
+ buffer.append(print(key, value, escapeChar));
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Print a parameter as a String.
+ *
+ * @param parameterName
+ * the name of the parameter to print
+ * @param parameterValue
+ * the value of the parameter to print
+ * @param escapeChar
+ * the character used in front of a special character when need to escape it
+ * @return the printed parameter
+ */
+ public String print(String parameterName, String parameterValue, char escapeChar) {
+ // escape the escaping character
+ String value = parameterValue.replace(String.valueOf(escapeChar), String.valueOf(escapeChar) + escapeChar);
+ // escape quote
+ value = value.replace(QUOTE, String.valueOf(escapeChar) + QUOTE);
+
+ return parameterName + "=" + QUOTE + value + QUOTE;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventBlockRenderer.java
new file mode 100644
index 000000000..71410a398
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventBlockRenderer.java
@@ -0,0 +1,37 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.event;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.rendering.internal.renderer.AbstractBlockRenderer;
+import org.xwiki.rendering.renderer.PrintRendererFactory;
+
+@Component("event/1.0")
+public class EventBlockRenderer extends AbstractBlockRenderer {
+
+ @Requirement("event/1.0")
+ private PrintRendererFactory eventRendererFactory;
+
+ @Override
+ protected PrintRendererFactory getPrintRendererFactory() {
+ return this.eventRendererFactory;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRenderer.java
new file mode 100644
index 000000000..01a39a00e
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRenderer.java
@@ -0,0 +1,59 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.event;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.InstantiationStrategy;
+import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
+import org.xwiki.component.phase.Initializable;
+import org.xwiki.component.phase.InitializationException;
+import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+
+/**
+ * Print names of events. Useful for debugging and tracing in general. Note that this class is not
+ * located in the test
+ * source tree since it's currently used at runtime by the WYSIWYG editor for its runtime debug
+ * mode.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("event/1.0")
+@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
+public class EventRenderer extends AbstractChainingPrintRenderer implements Initializable {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Initializable#initialize()
+ * @since 2.0M3
+ */
+ public void initialize() throws InitializationException {
+ ListenerChain chain = new ListenerChain();
+ setListenerChain(chain);
+
+ // Construct the listener chain in the right order. Listeners early in the chain are called
+ // before listeners
+ // placed later in the chain.
+ chain.addListener(this);
+ chain.addListener(new EventsChainingRenderer(chain));
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRendererFactory.java
new file mode 100644
index 000000000..80a3506ad
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRendererFactory.java
@@ -0,0 +1,43 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.event;
+
+import org.xwiki.rendering.internal.renderer.*;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.syntax.Syntax;
+
+/**
+ * Create XHTML Renderers.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("event/1.0")
+public class EventRendererFactory extends AbstractPrintRendererFactory {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractPrintRendererFactory#getSyntax()
+ */
+ public Syntax getSyntax() {
+ return Syntax.EVENT_1_0;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventsChainingRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventsChainingRenderer.java
new file mode 100644
index 000000000..23498518b
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventsChainingRenderer.java
@@ -0,0 +1,639 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.event;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.xwiki.rendering.listener.Format;
+import org.xwiki.rendering.listener.HeaderLevel;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.ListType;
+import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.rendering.syntax.Syntax;
+import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+
+/**
+ * Prints listener event names in a format useful for testing and debugging.
+ *
+ * @version $Id$
+ * @since 1.8RC1
+ */
+public class EventsChainingRenderer extends AbstractChainingPrintRenderer {
+
+ public EventsChainingRenderer(ListenerChain listenerChain) {
+ setListenerChain(listenerChain);
+ }
+
+ // Events
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDocument(java.util.Map)
+ */
+ @Override
+ public void beginDocument(Map parameters) {
+ getPrinter().println("beginDocument" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map)
+ */
+ @Override
+ public void endDocument(Map parameters) {
+ getPrinter().print("endDocument" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map)
+ */
+ @Override
+ public void beginGroup(Map parameters) {
+ getPrinter().println("beginGroup" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map)
+ */
+ @Override
+ public void endGroup(Map parameters) {
+ getPrinter().println("endGroup" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginFormat(org.xwiki.rendering.listener.Format,
+ * java.util.Map)
+ */
+ @Override
+ public void beginFormat(Format format, Map parameters) {
+ getPrinter().println("beginFormat [" + format + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endFormat(org.xwiki.rendering.listener.Format,
+ * java.util.Map)
+ */
+ @Override
+ public void endFormat(Format format, Map parameters) {
+ getPrinter().println("endFormat [" + format + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginParagraph(java.util.Map)
+ */
+ @Override
+ public void beginParagraph(Map parameters) {
+ getPrinter().println("beginParagraph" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endParagraph(java.util.Map)
+ */
+ @Override
+ public void endParagraph(Map parameters) {
+ getPrinter().println("endParagraph" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onNewLine()
+ */
+ @Override
+ public void onNewLine() {
+ getPrinter().println("onNewLine");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginLink(
+ * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map)
+ */
+ @Override
+ public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ getPrinter()
+ .println("beginLink [" + reference + "] [" + isFreeStandingURI + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endLink(
+ * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map)
+ */
+ @Override
+ public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ getPrinter()
+ .println("endLink [" + reference + "] [" + isFreeStandingURI + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onMacro(java.lang.String,
+ * java.util.Map,
+ * java.lang.String, boolean)
+ */
+ @Override
+ public void onMacro(String id, Map parameters, String content, boolean isInline) {
+ printMacroData("onMacro", id, parameters, content, isInline);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginSection(java.util.Map)
+ */
+ @Override
+ public void beginSection(Map parameters) {
+ getPrinter().println("beginSection" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginHeader(org.xwiki.rendering.listener.HeaderLevel,
+ * String, java.util.Map)
+ */
+ @Override
+ public void beginHeader(HeaderLevel level, String id, Map parameters) {
+ getPrinter().println("beginHeader [" + level + ", " + id + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endSection(java.util.Map)
+ */
+ @Override
+ public void endSection(Map parameters) {
+ getPrinter().println("endSection" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endHeader(
+ * org.xwiki.rendering.listener.HeaderLevel, String, java.util.Map)
+ */
+ @Override
+ public void endHeader(HeaderLevel level, String id, Map parameters) {
+ getPrinter().println("endHeader [" + level + ", " + id + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onWord(java.lang.String)
+ */
+ @Override
+ public void onWord(String word) {
+ getPrinter().println("onWord [" + getEscaped(word) + "]");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginList(org.xwiki.rendering.listener.ListType,
+ * java.util.Map)
+ */
+ @Override
+ public void beginList(ListType listType, Map parameters) {
+ getPrinter().println("beginList [" + listType + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginListItem()
+ */
+ @Override
+ public void beginListItem() {
+ getPrinter().println("beginListItem");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endList(org.xwiki.rendering.listener.ListType,
+ * java.util.Map)
+ */
+ @Override
+ public void endList(ListType listType, Map parameters) {
+ getPrinter().println("endList [" + listType + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endListItem()
+ */
+ @Override
+ public void endListItem() {
+ getPrinter().println("endListItem");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onSpace()
+ */
+ @Override
+ public void onSpace() {
+ getPrinter().println("onSpace");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onSpecialSymbol(char)
+ */
+ @Override
+ public void onSpecialSymbol(char symbol) {
+ getPrinter().println("onSpecialSymbol [" + symbol + "]");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onRawText(String, Syntax)
+ */
+ @Override
+ public void onRawText(String text, Syntax syntax) {
+ getPrinter().println("onRawText [" + text + "] [" + syntax.toIdString() + "]");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginMacroMarker(java.lang.String,
+ * java.util.Map,
+ * java.lang.String, boolean)
+ */
+ @Override
+ public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) {
+ printMacroData("beginMacroMarker", name, parameters, content, isInline);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endMacroMarker(java.lang.String,
+ * java.util.Map,
+ * java.lang.String, boolean)
+ */
+ @Override
+ public void endMacroMarker(String name, Map parameters, String content, boolean isInline) {
+ printMacroData("endMacroMarker", name, parameters, content, isInline);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onId(java.lang.String)
+ */
+ @Override
+ public void onId(String name) {
+ getPrinter().println("onId [" + name + "]");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onHorizontalLine(java.util.Map)
+ */
+ @Override
+ public void onHorizontalLine(Map parameters) {
+ getPrinter().println("onHorizontalLine" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onEmptyLines(int)
+ */
+ @Override
+ public void onEmptyLines(int count) {
+ getPrinter().println("onEmptyLines [" + count + "]");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onVerbatim(String, boolean,
+ * Map)
+ */
+ @Override
+ public void onVerbatim(String protectedString, boolean isInline, Map parameters) {
+ getPrinter()
+ .println("onVerbatim [" + protectedString + "] [" + isInline + "]" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionList(java.util.Map)
+ * @since 2.0RC1
+ */
+ @Override
+ public void beginDefinitionList(Map parameters) {
+ getPrinter().println("beginDefinitionList" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endDefinitionList(java.util.Map)
+ * @since 2.0RC1
+ */
+ @Override
+ public void endDefinitionList(Map parameters) {
+ getPrinter().println("endDefinitionList" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionTerm()
+ */
+ @Override
+ public void beginDefinitionTerm() {
+ getPrinter().println("beginDefinitionTerm");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionDescription()
+ */
+ @Override
+ public void beginDefinitionDescription() {
+ getPrinter().println("beginDefinitionDescription");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endDefinitionTerm()
+ */
+ @Override
+ public void endDefinitionTerm() {
+ getPrinter().println("endDefinitionTerm");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endDefinitionDescription()
+ */
+ @Override
+ public void endDefinitionDescription() {
+ getPrinter().println("endDefinitionDescription");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginQuotation(java.util.Map)
+ */
+ @Override
+ public void beginQuotation(Map parameters) {
+ getPrinter().println("beginQuotation" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endQuotation(java.util.Map)
+ */
+ @Override
+ public void endQuotation(Map parameters) {
+ getPrinter().println("endQuotation" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginQuotationLine()
+ */
+ @Override
+ public void beginQuotationLine() {
+ getPrinter().println("beginQuotationLine");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endQuotationLine()
+ */
+ @Override
+ public void endQuotationLine() {
+ getPrinter().println("endQuotationLine");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTable(java.util.Map)
+ */
+ @Override
+ public void beginTable(Map parameters) {
+ getPrinter().println("beginTable" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableCell(java.util.Map)
+ */
+ @Override
+ public void beginTableCell(Map parameters) {
+ getPrinter().println("beginTableCell" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableHeadCell(java.util.Map)
+ */
+ @Override
+ public void beginTableHeadCell(Map parameters) {
+ getPrinter().println("beginTableHeadCell" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableRow(java.util.Map)
+ */
+ @Override
+ public void beginTableRow(Map parameters) {
+ getPrinter().println("beginTableRow" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endTable(java.util.Map)
+ */
+ @Override
+ public void endTable(Map parameters) {
+ getPrinter().println("endTable" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endTableCell(java.util.Map)
+ */
+ @Override
+ public void endTableCell(Map parameters) {
+ getPrinter().println("endTableCell" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endTableHeadCell(java.util.Map)
+ */
+ @Override
+ public void endTableHeadCell(Map parameters) {
+ getPrinter().println("endTableHeadCell" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endTableRow(java.util.Map)
+ */
+ @Override
+ public void endTableRow(Map parameters) {
+ getPrinter().println("endTableRow" + serializeParameters(parameters));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onImage(
+ * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map)
+ * @since 2.5RC1
+ */
+ @Override
+ public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ getPrinter()
+ .println("onImage [" + reference + "] [" + isFreeStandingURI + "]" + serializeParameters(parameters));
+ }
+
+ public String getEscaped(String str) {
+ String printableStr;
+
+ if (str == null) {
+ printableStr = null;
+ } else if (StringUtils.isAsciiPrintable(str)) {
+ printableStr = str;
+ } else {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c > 126) {
+ buffer.append("(((").append((int) c).append(")))");
+ } else {
+ buffer.append(c);
+ }
+ }
+ printableStr = buffer.toString();
+ }
+
+ return printableStr;
+ }
+
+ private void printMacroData(String eventName, String name, Map parameters, String content,
+ boolean isInline) {
+ StringBuffer parametersBuffer = new StringBuffer();
+ for (Iterator paramsIt = parameters.keySet().iterator(); paramsIt.hasNext();) {
+ String paramName = paramsIt.next();
+ parametersBuffer.append(paramName).append("=").append(parameters.get(paramName));
+ if (paramsIt.hasNext()) {
+ parametersBuffer.append("|");
+ }
+ }
+
+ StringBuffer macroBuffer = new StringBuffer();
+
+ macroBuffer.append(eventName);
+ macroBuffer.append(isInline ? "Inline" : "Standalone");
+
+ macroBuffer.append(" [");
+ macroBuffer.append(name);
+ macroBuffer.append("]");
+
+ macroBuffer.append(" [");
+ macroBuffer.append(parametersBuffer);
+ macroBuffer.append("]");
+
+ if (content != null) {
+ macroBuffer.append(" [");
+ macroBuffer.append(content);
+ macroBuffer.append("]");
+ }
+
+ getPrinter().println(macroBuffer.toString());
+ }
+
+ private String serializeParameters(Map parameters) {
+ StringBuffer parametersStr = new StringBuffer();
+ for (Map.Entry entry : parameters.entrySet()) {
+ String value = entry.getValue();
+ String key = entry.getKey();
+
+ if (key != null && value != null) {
+ parametersStr.append('[').append(getEscaped(entry.getKey())).append(']').append('=').append('[')
+ .append(getEscaped(entry.getValue())).append(']');
+ }
+ }
+
+ if (parametersStr.length() > 0) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(' ').append('[');
+ buffer.append(parametersStr);
+ buffer.append(']');
+ return buffer.toString();
+ } else {
+ return "";
+ }
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextBlockRenderer.java
new file mode 100644
index 000000000..5586010a1
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextBlockRenderer.java
@@ -0,0 +1,55 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.plain;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.rendering.internal.renderer.AbstractBlockRenderer;
+import org.xwiki.rendering.renderer.PrintRendererFactory;
+
+/**
+ * Print only plain text information. For example it remove anything which need a specific syntax a
+ * simple plain text
+ * editor can't support like the style, link, image, etc. This renderer is mainly used to generate a
+ * simple as possible
+ * label like in a TOC.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("plain/1.0")
+public class PlainTextBlockRenderer extends AbstractBlockRenderer {
+
+ /**
+ * Used to create new plain/1.0 {@link org.xwiki.rendering.renderer.PrintRenderer}s.
+ */
+ @Requirement("plain/1.0")
+ private PrintRendererFactory plainTextRendererFactory;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.internal.renderer.AbstractBlockRenderer#getPrintRendererFactory()
+ */
+ @Override
+ protected PrintRendererFactory getPrintRendererFactory() {
+ return this.plainTextRendererFactory;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRenderer.java
new file mode 100644
index 000000000..af3332e6f
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRenderer.java
@@ -0,0 +1,333 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.plain;
+
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.xwiki.rendering.listener.HeaderLevel;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.reference.ResourceType;
+import org.xwiki.rendering.listener.ListType;
+import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
+import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
+import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator;
+import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+
+/**
+ * Print only plain text information. For example it remove anything which need a specific syntax a
+ * simple plain text
+ * editor can't support like the style, link, image, etc. This renderer is mainly used to generate a
+ * simple as possible
+ * label like in a TOC.
+ *
+ * @version $Id$
+ * @since 1.9M1
+ */
+public class PlainTextChainingRenderer extends AbstractChainingPrintRenderer {
+
+ /**
+ * New Line character.
+ */
+ private static final String NL = "\n";
+
+ private boolean isFirstElementRendered;
+
+ /**
+ * Generate link label.
+ */
+ private LinkLabelGenerator linkLabelGenerator;
+
+ /**
+ * The plain text renderer supports when no link label generator is set.
+ */
+ public PlainTextChainingRenderer(ListenerChain listenerChain) {
+ this(null, listenerChain);
+ }
+
+ public PlainTextChainingRenderer(LinkLabelGenerator linkLabelGenerator, ListenerChain listenerChain) {
+ setListenerChain(listenerChain);
+
+ this.linkLabelGenerator = linkLabelGenerator;
+ }
+
+ // State
+
+ private BlockStateChainingListener getBlockState() {
+ return (BlockStateChainingListener) getListenerChain().getListener(BlockStateChainingListener.class);
+ }
+
+ protected EmptyBlockChainingListener getEmptyBlockState() {
+ return (EmptyBlockChainingListener) getListenerChain().getListener(EmptyBlockChainingListener.class);
+ }
+
+ // Events
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginParagraph(java.util.Map)
+ */
+ @Override
+ public void beginParagraph(Map parameters) {
+ printEmptyLine();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onNewLine()
+ */
+ @Override
+ public void onNewLine() {
+ getPrinter().print(NL);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink(
+ * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map)
+ */
+ @Override
+ public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ if (getEmptyBlockState().isCurrentContainerBlockEmpty()) {
+ if (reference.getType().equals(ResourceType.DOCUMENT) && this.linkLabelGenerator != null) {
+ getPrinter().print(this.linkLabelGenerator.generate(reference));
+ } else {
+ getPrinter().print(reference.getReference());
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginHeader(org.xwiki.rendering.listener.HeaderLevel,
+ * String, java.util.Map)
+ */
+ @Override
+ public void beginHeader(HeaderLevel level, String id, Map parameters) {
+ printEmptyLine();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onWord(java.lang.String)
+ */
+ @Override
+ public void onWord(String word) {
+ getPrinter().print(word);
+ }
+
+ @Override
+ public void beginList(ListType listType, Map parameters) {
+ if (getBlockState().getListDepth() == 1) {
+ printEmptyLine();
+ } else {
+ getPrinter().print(NL);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginListItem()
+ */
+ @Override
+ public void beginListItem() {
+ if (getBlockState().getListItemIndex() > 0) {
+ getPrinter().print(NL);
+ }
+
+ // TODO: maybe add some syntax here like a - or not
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onSpace()
+ */
+ @Override
+ public void onSpace() {
+ getPrinter().print(" ");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onSpecialSymbol(char)
+ */
+ @Override
+ public void onSpecialSymbol(char symbol) {
+ getPrinter().print(String.valueOf(symbol));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onHorizontalLine(java.util.Map)
+ */
+ @Override
+ public void onHorizontalLine(Map parameters) {
+ printEmptyLine();
+ getPrinter().print("----");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onEmptyLines(int)
+ */
+ @Override
+ public void onEmptyLines(int count) {
+ getPrinter().print(StringUtils.repeat(NL, count));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onVerbatim(String, boolean,
+ * Map)
+ */
+ @Override
+ public void onVerbatim(String protectedString, boolean isInline, Map parameters) {
+ getPrinter().print(protectedString);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map)
+ * @since 2.0RC1
+ */
+ @Override
+ public void beginDefinitionList(Map parameters) {
+ if (getBlockState().getDefinitionListDepth() == 1 && !getBlockState().isInList()) {
+ printEmptyLine();
+ } else {
+ getPrinter().print(NL);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionTerm()
+ */
+ @Override
+ public void beginDefinitionTerm() {
+ if (getBlockState().getDefinitionListItemIndex() > 0) {
+ getPrinter().print(NL);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionDescription()
+ */
+ @Override
+ public void beginDefinitionDescription() {
+ if (getBlockState().getDefinitionListItemIndex() > 0) {
+ getPrinter().print(NL);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginQuotationLine()
+ */
+ @Override
+ public void beginQuotationLine() {
+ if (getBlockState().getQuotationLineIndex() > 0) {
+ getPrinter().print(NL);
+ } else {
+ printEmptyLine();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTable(java.util.Map)
+ */
+ @Override
+ public void beginTable(Map parameters) {
+ printEmptyLine();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableCell(java.util.Map)
+ */
+ @Override
+ public void beginTableCell(Map parameters) {
+ if (getBlockState().getCellCol() > 0) {
+ getPrinter().print("\t");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableHeadCell(java.util.Map)
+ */
+ @Override
+ public void beginTableHeadCell(Map parameters) {
+ beginTableCell(parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableRow(java.util.Map)
+ */
+ @Override
+ public void beginTableRow(Map parameters) {
+ if (getBlockState().getCellRow() > 0) {
+ getPrinter().print(NL);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onImage(
+ * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map)
+ * @since 2.5RC1
+ */
+ @Override
+ public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ // TODO: maybe something could be done here
+ }
+
+ private void printEmptyLine() {
+ if (this.isFirstElementRendered) {
+ getPrinter().print(NL + NL);
+ } else {
+ this.isFirstElementRendered = true;
+ }
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRenderer.java
new file mode 100644
index 000000000..a1d12a089
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRenderer.java
@@ -0,0 +1,69 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.plain;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.InstantiationStrategy;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
+import org.xwiki.component.phase.Initializable;
+import org.xwiki.component.phase.InitializationException;
+import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
+import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
+import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator;
+import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+
+/**
+ * Print only plain text information. For example it remove anything which need a specific syntax a
+ * simple plain text
+ * editor can't support like the style, link, image, etc. This renderer is mainly used to generate a
+ * simple as possible
+ * label like in a TOC.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("plain/1.0")
+@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
+public class PlainTextRenderer extends AbstractChainingPrintRenderer implements Initializable {
+
+ @Requirement
+ private LinkLabelGenerator linkLabelGenerator;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Initializable#initialize()
+ * @since 2.0M3
+ */
+ public void initialize() throws InitializationException {
+ ListenerChain chain = new ListenerChain();
+ setListenerChain(chain);
+
+ // Construct the listener chain in the right order. Listeners early in the chain are called
+ // before listeners
+ // placed later in the chain.
+ chain.addListener(this);
+ chain.addListener(new BlockStateChainingListener(chain));
+ chain.addListener(new EmptyBlockChainingListener(chain));
+ chain.addListener(new PlainTextChainingRenderer(this.linkLabelGenerator, chain));
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRendererFactory.java
new file mode 100644
index 000000000..08696b739
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRendererFactory.java
@@ -0,0 +1,43 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.plain;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.syntax.Syntax;
+import org.xwiki.rendering.internal.renderer.AbstractPrintRendererFactory;
+
+/**
+ * Create Plain Text Renderers.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("plain/1.0")
+public class PlainTextRendererFactory extends AbstractPrintRendererFactory {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractPrintRendererFactory#getSyntax()
+ */
+ public Syntax getSyntax() {
+ return Syntax.PLAIN_1_0;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/WikiWriter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/WikiWriter.java
new file mode 100644
index 000000000..12d603615
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/WikiWriter.java
@@ -0,0 +1,90 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.printer;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.xwiki.rendering.renderer.printer.WikiPrinter;
+
+/**
+ * Bridge so that {@link WikiPrinter} can be used in a tools supporting {@link Writer} api.
+ *
+ * @version $Id$
+ */
+public class WikiWriter extends Writer {
+
+ public WikiWriter(WikiPrinter printer) {
+ super(printer);
+ }
+
+ public void setWikiPrinter(WikiPrinter printer) {
+ this.lock = printer;
+ }
+
+ public WikiPrinter getWikiPrinter() {
+ return (WikiPrinter) this.lock;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.io.Writer#close()
+ */
+ @Override
+ public void close() throws IOException {
+ // WikiPrinter does not support stream close
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.io.Writer#flush()
+ */
+ @Override
+ public void flush() throws IOException {
+ // WikiPrinter does not support stream flush
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.io.Writer#write(char[], int, int)
+ */
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ getWikiPrinter().print(new String(cbuf, off, len));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Override it to improve speed a little. Otherwise the String is transformed in char table passed
+ * to the over
+ * methods which recreate a String.
+ *
+ * @see java.io.Writer#write(java.lang.String)
+ */
+ @Override
+ public void write(String str) throws IOException {
+ getWikiPrinter().print(str);
+ }
+
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XHTMLWriter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XHTMLWriter.java
new file mode 100644
index 000000000..5be64c032
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XHTMLWriter.java
@@ -0,0 +1,62 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.printer;
+
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.XMLWriter;
+
+/**
+ * XHTMLWriter is an helper to configure XMLWriter to format a DOM4J tree as XHTML.
+ *
+ * @version $Id$
+ */
+public class XHTMLWriter extends XMLWriter {
+
+ protected static final OutputFormat DEFAULT_XHTML_FORMAT;
+
+ static {
+ DEFAULT_XHTML_FORMAT = new OutputFormat();
+ DEFAULT_XHTML_FORMAT.setXHTML(true);
+ }
+
+ public XHTMLWriter(Writer writer) throws UnsupportedEncodingException {
+ super(writer, DEFAULT_XHTML_FORMAT);
+
+ // escape all non US-ASCII to have as less encoding problems as possible
+ setMaximumAllowedCharacter(-1);
+ }
+
+ /**
+ * Escapes a string to be used as an attribute value. Unlike the original method in
+ * {@link XMLWriter}, apostrophes
+ * are replaced by a numerical entity &, since ' is not valid in HTML documents.
+ *
+ * @param text
+ * the attribute value to escape
+ * @return the text with all occurrences of special XML characters replaced by entity references.
+ */
+ @Override
+ protected String escapeAttributeEntities(String text) {
+ return super.escapeAttributeEntities(text).replace("'", "&");
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XWikiSyntaxEscapeWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XWikiSyntaxEscapeWikiPrinter.java
new file mode 100644
index 000000000..ae1e3f2b9
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XWikiSyntaxEscapeWikiPrinter.java
@@ -0,0 +1,272 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.printer;
+
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxEscapeHandler;
+import org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxListenerChain;
+import org.xwiki.rendering.renderer.printer.LookaheadWikiPrinter;
+import org.xwiki.rendering.renderer.printer.WikiPrinter;
+
+/**
+ * A Wiki printer that knows how to escape characters that would otherwise mean something different
+ * in XWiki wiki
+ * syntax. For example if we have "**" as special symbols (and not as a Bold Format block) we need
+ * to escape them to
+ * "~*~*" as otherwise they'd be considered bold after being rendered.
+ *
+ * @version $Id$
+ * @since 1.7
+ */
+public class XWikiSyntaxEscapeWikiPrinter extends LookaheadWikiPrinter {
+
+ private static final Pattern VERBATIM_PATTERN = Pattern.compile("(\\{\\{\\{)|(\\}\\}\\})");
+
+ private XWikiSyntaxListenerChain listenerChain;
+
+ private XWikiSyntaxEscapeHandler escapeHandler;
+
+ private boolean escapeLastChar;
+
+ private Pattern escapeFirstIfMatching;
+
+ private String lastPrinted;
+
+ public XWikiSyntaxEscapeWikiPrinter(WikiPrinter printer, XWikiSyntaxListenerChain listenerChain) {
+ super(printer);
+
+ this.escapeHandler = new XWikiSyntaxEscapeHandler();
+
+ this.listenerChain = listenerChain;
+ }
+
+ public XWikiSyntaxEscapeHandler getEscapeHandler() {
+ return escapeHandler;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.printer.LookaheadWikiPrinter#printInternal(java.lang.String)
+ */
+ @Override
+ protected void printInternal(String text) {
+ super.printInternal(text);
+
+ int length = text.length();
+
+ if (length > 0) {
+ this.escapeHandler.setOnNewLine(text.charAt(length - 1) == '\n');
+ }
+
+ this.lastPrinted = text;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.printer.LookaheadWikiPrinter#println(java.lang.String)
+ */
+ @Override
+ protected void printlnInternal(String text) {
+ super.printlnInternal(text);
+
+ this.escapeHandler.setOnNewLine(true);
+
+ this.lastPrinted = "\n";
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.printer.LookaheadWikiPrinter#flush()
+ */
+ @Override
+ public void flush() {
+ if (getBuffer().length() > 0) {
+ this.escapeHandler.escape(getBuffer(), this.listenerChain, this.escapeLastChar, this.escapeFirstIfMatching);
+ super.flush();
+ }
+ this.escapeLastChar = false;
+ this.escapeFirstIfMatching = null;
+ }
+
+ public void printBeginBold() {
+ flush();
+
+ boolean isOnNewLine = this.escapeHandler.isOnNewLine();
+
+ print("**");
+
+ if (isOnNewLine) {
+ this.escapeFirstIfMatching = XWikiSyntaxEscapeHandler.STARLISTEND_PATTERN;
+ }
+ }
+
+ public void setEscapeLastChar(boolean escapeLastChar) {
+ this.escapeLastChar = escapeLastChar;
+ }
+
+ public void setBeforeLink(boolean beforeLink) {
+ this.escapeHandler.setBeforeLink(beforeLink);
+ }
+
+ public void setOnNewLine(boolean onNewLine) {
+ this.escapeHandler.setOnNewLine(onNewLine);
+ }
+
+ public boolean isOnNewLine() {
+ return this.escapeHandler.isOnNewLine();
+ }
+
+ public boolean isAfterWhiteSpace() {
+ return isOnNewLine() || Character.isWhitespace(getLastPrinted().charAt(getLastPrinted().length() - 1));
+ }
+
+ public String getLastPrinted() {
+ return this.lastPrinted;
+ }
+
+ public void printBeginItalic() {
+ // If the lookahead buffer is not empty and the last character is ":" then we need to escape it
+ // since otherwise we would get "://" which could be confused for a URL.
+ if (getBuffer().length() > 0 && getBuffer().charAt(getBuffer().length() - 1) == ':') {
+ this.escapeLastChar = true;
+ }
+
+ print("//");
+ }
+
+ public void printEndItalic() {
+ // If the lookahead buffer is not empty and the last character is ":" then we need to escape it
+ // since otherwise we would get "://" which could be confused for a URL.
+ if (getBuffer().length() > 0 && getBuffer().charAt(getBuffer().length() - 1) == ':') {
+ this.escapeLastChar = true;
+ }
+
+ print("//");
+ }
+
+ public void printInlineMacro(String xwikiSyntaxText) {
+ // If the lookahead buffer is not empty and the last character is "{" then we need to escape it
+ // since otherwise we would get "{{{" which could be confused for a verbatim block.
+ if (getBuffer().length() > 0 && getBuffer().charAt(getBuffer().length() - 1) == '{') {
+ this.escapeLastChar = true;
+ }
+
+ print(xwikiSyntaxText);
+ }
+
+ public void printVerbatimContent(String verbatimContent) {
+ StringBuffer result = new StringBuffer();
+
+ Stack subVerbatimStack = new Stack();
+ boolean printEndVerbatim = false;
+
+ Matcher matcher = VERBATIM_PATTERN.matcher(verbatimContent);
+ int currentIndex = 0;
+ for (; matcher.find(); currentIndex = matcher.end()) {
+ String before = verbatimContent.substring(currentIndex, matcher.start());
+
+ if (printEndVerbatim) {
+ if (before.startsWith("}")) {
+ result.append("~}~}~}");
+ } else {
+ result.append("~}}}");
+ }
+ }
+
+ if (subVerbatimStack.size() == 0) {
+ result.append(before);
+ } else {
+ subVerbatimStack.peek().append(before);
+ }
+
+ if (matcher.group(1) != null) {
+ subVerbatimStack.push(new StringBuffer());
+ } else {
+ if (subVerbatimStack.size() == 0) {
+ printEndVerbatim = true;
+ } else {
+ StringBuffer subVerbatim = subVerbatimStack.pop();
+
+ if (subVerbatimStack.size() == 0) {
+ result.append("{{{");
+ result.append(subVerbatim);
+ result.append("}}}");
+ } else {
+ subVerbatimStack.peek().append("{{{");
+ subVerbatimStack.peek().append(subVerbatim);
+ subVerbatimStack.peek().append("}}}");
+ }
+ }
+ }
+ }
+
+ if (currentIndex == 0) {
+ print(verbatimContent);
+ return;
+ }
+
+ String end = verbatimContent.substring(currentIndex);
+
+ if (printEndVerbatim) {
+ if (end.length() == 0 || end.charAt(0) == '}') {
+ result.append("~}~}~}");
+ } else {
+ result.append("~}}}");
+ }
+ }
+
+ if (subVerbatimStack.size() > 0) {
+ // Append remaining string
+ subVerbatimStack.peek().append(end);
+
+ // Escape not closed verbatim blocks
+ while (subVerbatimStack.size() > 0) {
+ StringBuffer subVerbatim = subVerbatimStack.pop();
+
+ if (subVerbatimStack.size() == 0) {
+ if (subVerbatim.length() > 0 && subVerbatim.charAt(0) == '{') {
+ result.append("~{~{~{");
+ } else {
+ result.append("~{{{");
+ }
+ result.append(subVerbatim);
+ } else {
+ if (subVerbatim.length() > 0 && subVerbatim.charAt(0) == '{') {
+ subVerbatimStack.peek().append("~{~{~{");
+ } else {
+ subVerbatimStack.peek().append("~{{{");
+ }
+ subVerbatimStack.peek().append(subVerbatim);
+ }
+ }
+ } else {
+ // Append remaining string
+ result.append(end);
+ }
+
+ print(result.toString());
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLBlockRenderer.java
new file mode 100644
index 000000000..bba582bbb
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLBlockRenderer.java
@@ -0,0 +1,48 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.xhtml;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.rendering.internal.renderer.AbstractBlockRenderer;
+import org.xwiki.rendering.renderer.PrintRendererFactory;
+
+/**
+ * Block Renderer for Annotated XHTML syntax. To be used to convert XDOM into XHTML.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("annotatedxhtml/1.0")
+public class AnnotatedXHTMLBlockRenderer extends AbstractBlockRenderer {
+
+ @Requirement("annotatedxhtml/1.0")
+ private PrintRendererFactory annotatedXHTMLRendererFactory;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.internal.renderer.AbstractBlockRenderer#getPrintRendererFactory()
+ */
+ @Override
+ protected PrintRendererFactory getPrintRendererFactory() {
+ return this.annotatedXHTMLRendererFactory;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java
new file mode 100644
index 000000000..21704f314
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java
@@ -0,0 +1,104 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.xhtml;
+
+import java.util.Map;
+
+import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
+import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
+import org.xwiki.rendering.listener.chaining.ListenerChain;
+
+/**
+ * Convert listener events to annotated XHTML. See {@link AnnotatedXHTMLChainingRenderer} for more
+ * details on what
+ * Annotated XHTML is.
+ *
+ * @version $Id$
+ * @since 2.0M2
+ */
+public class AnnotatedXHTMLChainingRenderer extends XHTMLChainingRenderer {
+
+ private XHTMLMacroRenderer macroRenderer;
+
+ /**
+ * @param linkRenderer
+ * the object to render link events into XHTML. This is done so that it's pluggable
+ * because link
+ * rendering depends on how the underlying system wants to handle it. For example for
+ * XWiki we check if
+ * the document exists, we get the document URL, etc.
+ * @param imageRenderer
+ * the object to render image events into XHTML. This is done so that it's pluggable
+ * because image
+ * rendering depends on how the underlying system wants to handle it. For example for
+ * XWiki we check if
+ * the image exists as a document attachments, we get its URL, etc.
+ * @param listenerChain
+ * the chain of listener filters used to compute various states
+ */
+ public AnnotatedXHTMLChainingRenderer(XHTMLLinkRenderer linkRenderer, XHTMLImageRenderer imageRenderer,
+ ListenerChain listenerChain) {
+ super(linkRenderer, imageRenderer, listenerChain);
+
+ this.macroRenderer = new XHTMLMacroRenderer();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.Renderer#onMacro(String, java.util.Map, String, boolean)
+ */
+ @Override
+ public void onMacro(String id, Map parameters, String content, boolean isInline) {
+ // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
+ // so that the macro can be reconstructed when moving back from XHTML to XDOM.
+ this.macroRenderer.render(getXHTMLWikiPrinter(), id, parameters, content);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.Renderer#beginMacroMarker(String, java.util.Map, String,
+ * boolean)
+ */
+ @Override
+ public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) {
+ if (getBlockState().getMacroDepth() == 1) {
+ // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
+ // so that the macro can be reconstructed when moving back from XHTML to XDOM.
+ this.macroRenderer.beginRender(getXHTMLWikiPrinter(), name, parameters, content);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.Renderer#endMacroMarker(String, java.util.Map, String,
+ * boolean)
+ */
+ @Override
+ public void endMacroMarker(String name, Map parameters, String content, boolean isInline) {
+ if (getBlockState().getMacroDepth() == 1) {
+ // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
+ // so that the macro can be reconstructed when moving back from XHTML to XDOM.
+ this.macroRenderer.endRender(getXHTMLWikiPrinter());
+ }
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java
new file mode 100644
index 000000000..db37d08bc
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java
@@ -0,0 +1,89 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.xhtml;
+
+import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
+import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
+import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
+import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
+import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.InstantiationStrategy;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
+import org.xwiki.component.phase.InitializationException;
+import org.xwiki.component.phase.Initializable;
+
+/**
+ * Generates Annotated XHTML (ie XHTML containing metadata information, for example macro definition
+ * or link definition)
+ * from a {@link org.xwiki.rendering.block.XDOM} object being traversed. The annotations allow
+ * initial source content to
+ * be fully reconstructed from the generated XHTML. This is required for example for doing round
+ * tripping between wiki
+ * syntax and XHTML syntax in the WYSIWYG editor.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("annotatedxhtml/1.0")
+@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
+public class AnnotatedXHTMLRenderer extends AbstractChainingPrintRenderer implements Initializable {
+
+ /**
+ * To render link events into annotated XHTML. This is done so that it's pluggable because link
+ * rendering depends on
+ * how the underlying system wants to handle it. For example for XWiki we check if the document
+ * exists, we get the
+ * document URL, etc.
+ */
+ @Requirement("annotated")
+ private XHTMLLinkRenderer linkRenderer;
+
+ /**
+ * To render image events into annotated XHTML. This is done so that it's pluggable because image
+ * rendering depends
+ * on how the underlying system wants to handle it. For example for XWiki we check if the image
+ * exists as a document
+ * attachments, we get its URL, etc.
+ */
+ @Requirement("annotated")
+ private XHTMLImageRenderer imageRenderer;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.component.phase.Initializable#initialize()
+ * @since 2.0M3
+ */
+ public void initialize() throws InitializationException {
+ ListenerChain chain = new ListenerChain();
+ setListenerChain(chain);
+
+ // Construct the listener chain in the right order. Listeners early in the chain are called
+ // before listeners
+ // placed later in the chain.
+ chain.addListener(this);
+ chain.addListener(new BlockStateChainingListener(chain));
+ chain.addListener(new EmptyBlockChainingListener(chain));
+ chain.addListener(new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRendererFactory.java
new file mode 100644
index 000000000..b7f5cbad7
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRendererFactory.java
@@ -0,0 +1,43 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.xhtml;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.rendering.internal.renderer.AbstractPrintRendererFactory;
+import org.xwiki.rendering.syntax.Syntax;
+
+/**
+ * Create Annotated XHTML Renderers.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("annotatedxhtml/1.0")
+public class AnnotatedXHTMLRendererFactory extends AbstractPrintRendererFactory {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractPrintRendererFactory#getSyntax()
+ */
+ public Syntax getSyntax() {
+ return Syntax.ANNOTATED_XHTML_1_0;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLBlockRenderer.java
new file mode 100644
index 000000000..b3627655b
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLBlockRenderer.java
@@ -0,0 +1,48 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.xhtml;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.rendering.internal.renderer.AbstractBlockRenderer;
+import org.xwiki.rendering.renderer.PrintRendererFactory;
+
+/**
+ * Block Renderer for XHTML syntax. To be used to convert XDOM into XHTML.
+ *
+ * @version $Id$
+ * @since 2.0M3
+ */
+@Component("xhtml/1.0")
+public class XHTMLBlockRenderer extends AbstractBlockRenderer {
+
+ @Requirement("xhtml/1.0")
+ private PrintRendererFactory xhtmlRendererFactory;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.internal.renderer.AbstractBlockRenderer#getPrintRendererFactory()
+ */
+ @Override
+ protected PrintRendererFactory getPrintRendererFactory() {
+ return this.xhtmlRendererFactory;
+ }
+}
diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java
new file mode 100644
index 000000000..5ed40728b
--- /dev/null
+++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java
@@ -0,0 +1,715 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.renderer.xhtml;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
+import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
+import org.xwiki.rendering.listener.Format;
+import org.xwiki.rendering.listener.HeaderLevel;
+import org.xwiki.rendering.listener.reference.ResourceReference;
+import org.xwiki.rendering.listener.ListType;
+import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
+import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
+import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.rendering.listener.chaining.BlockStateChainingListener.Event;
+import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.rendering.renderer.printer.WikiPrinter;
+import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter;
+import org.xwiki.rendering.syntax.Syntax;
+import org.xwiki.rendering.syntax.SyntaxType;
+
+/**
+ * Convert listener events to XHTML.
+ *
+ * @version $Id$
+ * @since 1.8RC1
+ */
+public class XHTMLChainingRenderer extends AbstractChainingPrintRenderer {
+
+ private XHTMLLinkRenderer linkRenderer;
+
+ private XHTMLImageRenderer imageRenderer;
+
+ private XHTMLWikiPrinter xhtmlWikiPrinter;
+
+ /**
+ * @param linkRenderer
+ * the object to render link events into XHTML. This is done so that it's pluggable
+ * because link
+ * rendering depends on how the underlying system wants to handle it. For example for
+ * XWiki we check if
+ * the document exists, we get the document URL, etc.
+ * @param imageRenderer
+ * the object to render image events into XHTML. This is done so that it's pluggable
+ * because image
+ * rendering depends on how the underlying system wants to handle it. For example for
+ * XWiki we check if
+ * the image exists as a document attachments, we get its URL, etc.
+ * @param listenerChain
+ * the chain of listener filters used to compute various states
+ */
+ public XHTMLChainingRenderer(XHTMLLinkRenderer linkRenderer, XHTMLImageRenderer imageRenderer,
+ ListenerChain listenerChain) {
+ setListenerChain(listenerChain);
+
+ this.linkRenderer = linkRenderer;
+ this.imageRenderer = imageRenderer;
+ }
+
+ // State
+
+ protected BlockStateChainingListener getBlockState() {
+ return (BlockStateChainingListener) getListenerChain().getListener(BlockStateChainingListener.class);
+ }
+
+ protected EmptyBlockChainingListener getEmptyBlockState() {
+ return (EmptyBlockChainingListener) getListenerChain().getListener(EmptyBlockChainingListener.class);
+ }
+
+ // Printer
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#pushPrinter(org.xwiki.rendering.renderer.printer.WikiPrinter)
+ */
+ @Override
+ protected void pushPrinter(WikiPrinter wikiPrinter) {
+ super.pushPrinter(wikiPrinter);
+ getXHTMLWikiPrinter().setWikiPrinter(getPrinter());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#popPrinter()
+ */
+ @Override
+ protected void popPrinter() {
+ super.popPrinter();
+ getXHTMLWikiPrinter().setWikiPrinter(getPrinter());
+ }
+
+ protected XHTMLWikiPrinter getXHTMLWikiPrinter() {
+ if (this.xhtmlWikiPrinter == null) {
+ this.xhtmlWikiPrinter = new XHTMLWikiPrinter(getPrinter());
+ }
+ return this.xhtmlWikiPrinter;
+ }
+
+ // Events
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#beginGroup(Map)
+ */
+ @Override
+ public void beginGroup(Map parameters) {
+ Map clonedParameters = new LinkedHashMap();
+ clonedParameters.putAll(parameters);
+ getXHTMLWikiPrinter().printXMLStartElement("div", clonedParameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#endGroup(Map)
+ */
+ @Override
+ public void endGroup(Map parameters) {
+ getXHTMLWikiPrinter().printXMLEndElement("div");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#beginFormat(Format, java.util.Map)
+ */
+ @Override
+ public void beginFormat(Format format, Map parameters) {
+ switch (format) {
+ case BOLD:
+ getXHTMLWikiPrinter().printXMLStartElement("strong");
+ break;
+ case ITALIC:
+ getXHTMLWikiPrinter().printXMLStartElement("em");
+ break;
+ case STRIKEDOUT:
+ getXHTMLWikiPrinter().printXMLStartElement("del");
+ break;
+ case UNDERLINED:
+ getXHTMLWikiPrinter().printXMLStartElement("ins");
+ break;
+ case SUPERSCRIPT:
+ getXHTMLWikiPrinter().printXMLStartElement("sup");
+ break;
+ case SUBSCRIPT:
+ getXHTMLWikiPrinter().printXMLStartElement("sub");
+ break;
+ case MONOSPACE:
+ getXHTMLWikiPrinter().printXMLStartElement("tt");
+ break;
+ }
+ if (!parameters.isEmpty()) {
+ getXHTMLWikiPrinter().printXMLStartElement("span", parameters);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#endFormat(Format, Map)
+ */
+ @Override
+ public void endFormat(Format format, Map parameters) {
+ if (!parameters.isEmpty()) {
+ getXHTMLWikiPrinter().printXMLEndElement("span");
+ }
+ switch (format) {
+ case BOLD:
+ getXHTMLWikiPrinter().printXMLEndElement("strong");
+ break;
+ case ITALIC:
+ getXHTMLWikiPrinter().printXMLEndElement("em");
+ break;
+ case STRIKEDOUT:
+ getXHTMLWikiPrinter().printXMLEndElement("del");
+ break;
+ case UNDERLINED:
+ getXHTMLWikiPrinter().printXMLEndElement("ins");
+ break;
+ case SUPERSCRIPT:
+ getXHTMLWikiPrinter().printXMLEndElement("sup");
+ break;
+ case SUBSCRIPT:
+ getXHTMLWikiPrinter().printXMLEndElement("sub");
+ break;
+ case MONOSPACE:
+ getXHTMLWikiPrinter().printXMLEndElement("tt");
+ break;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#beginParagraph(java.util.Map)
+ */
+ @Override
+ public void beginParagraph(Map parameters) {
+ getXHTMLWikiPrinter().printXMLStartElement("p", parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#endParagraph(java.util.Map)
+ */
+ @Override
+ public void endParagraph(Map parameters) {
+ getXHTMLWikiPrinter().printXMLEndElement("p");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#onNewLine()
+ */
+ @Override
+ public void onNewLine() {
+ getXHTMLWikiPrinter().printXMLElement("br");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#beginLink(org.xwiki.rendering.listener.reference.ResourceReference
+ * , boolean,
+ * Map)
+ */
+ @Override
+ public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ // Ensure the link renderer is using the latest printer since the original printer used could
+ // have been
+ // superseded by another one in the printer stack.
+ this.linkRenderer.setXHTMLWikiPrinter(getXHTMLWikiPrinter());
+
+ this.linkRenderer.beginLink(reference, isFreeStandingURI, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#endLink(org.xwiki.rendering.listener.reference.ResourceReference
+ * , boolean,
+ * Map)
+ */
+ @Override
+ public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) {
+ this.linkRenderer.setHasLabel(!getEmptyBlockState().isCurrentContainerBlockEmpty());
+ this.linkRenderer.endLink(reference, isFreeStandingURI, parameters);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#beginHeader(HeaderLevel, String, Map)
+ */
+ @Override
+ public void beginHeader(HeaderLevel level, String id, Map parameters) {
+ Map attributes = new LinkedHashMap();
+
+ attributes.put("id", id);
+ attributes.putAll(parameters);
+
+ // Section editing feature:
+ // In order for the UI side to be able to add a section edit button we need to provide some
+ // information to it
+ // and especially we need to tell it if the header was a header generated by a macro or not. The
+ // reason is
+ // that macro-generated headers should not be editable by the user.
+ // TODO: In the future it's possible that we'll want this kind of behavior implemented using a
+ // Transformation.
+ // If we decide this then remove this code.
+ if (getBlockState().isInMacro()) {
+ String classAttributeName = "class";
+ String classValue = attributes.get(classAttributeName);
+ String newClassValue = "wikigeneratedheader";
+ if (classValue == null) {
+ classValue = newClassValue;
+ } else {
+ classValue = classValue.trim() + " " + newClassValue;
+ }
+ attributes.put(classAttributeName, classValue);
+ }
+
+ getXHTMLWikiPrinter().printXMLStartElement("h" + level.getAsInt(), attributes);
+ // We generate a span so that CSS rules have a hook to perform some magic that wouldn't work on
+ // just a H
+ // element. Like some IE6 magic and others.
+ getXHTMLWikiPrinter().printXMLStartElement("span");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#endHeader(HeaderLevel, String, Map)
+ */
+ @Override
+ public void endHeader(HeaderLevel level, String id, Map parameters) {
+ getXHTMLWikiPrinter().printXMLEndElement("span");
+ getXHTMLWikiPrinter().printXMLEndElement("h" + level.getAsInt());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#onWord(String)
+ */
+ @Override
+ public void onWord(String word) {
+ getXHTMLWikiPrinter().printXML(word);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#onSpace()
+ */
+ @Override
+ public void onSpace() {
+ // The XHTML printer will decide whether to print a normal space or a
+ getXHTMLWikiPrinter().printSpace();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#onSpecialSymbol(char)
+ */
+ @Override
+ public void onSpecialSymbol(char symbol) {
+ getXHTMLWikiPrinter().printXML("" + symbol);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#beginList(org.xwiki.rendering.listener.ListType,
+ * java.util.Map)
+ */
+ @Override
+ public void beginList(ListType listType, Map parameters) {
+ if (listType == ListType.BULLETED) {
+ getXHTMLWikiPrinter().printXMLStartElement("ul", parameters);
+ } else {
+ getXHTMLWikiPrinter().printXMLStartElement("ol", parameters);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#beginListItem()
+ */
+ @Override
+ public void beginListItem() {
+ getXHTMLWikiPrinter().printXMLStartElement("li");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#endList(org.xwiki.rendering.listener.ListType,
+ * java.util.Map)
+ */
+ @Override
+ public void endList(ListType listType, Map parameters) {
+ if (listType == ListType.BULLETED) {
+ getXHTMLWikiPrinter().printXMLEndElement("ul");
+ } else {
+ getXHTMLWikiPrinter().printXMLEndElement("ol");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#endListItem()
+ */
+ @Override
+ public void endListItem() {
+ getXHTMLWikiPrinter().printXMLEndElement("li");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see AbstractChainingPrintRenderer#onId(String)
+ */
+ @Override
+ public void onId(String name) {
+ // Don't use the "name" attribute (see http://www.w3.org/TR/html4/struct/links.html#h-12.2.3).
+ // If the id s in a paragraph use and if in a standalone block then use
+ // .
+ if (getBlockState().isInLine()) {
+ // Note: We're using