diff --git a/celements-xwiki-rendering-api/pom.xml b/celements-xwiki-rendering-api/pom.xml new file mode 100644 index 000000000..1320f4694 --- /dev/null +++ b/celements-xwiki-rendering-api/pom.xml @@ -0,0 +1,251 @@ + + + + + + 4.0.0 + + com.celements + base-pom + 7.0-SNAPSHOT + + celements-xwiki-rendering-api + 7.0-SNAPSHOT + + + com.celements + celements-commons + 7.0-SNAPSHOT + provided + + + com.celements + celements-component + 7.0-SNAPSHOT + provided + + + com.celements + celements-reference + 7.0-SNAPSHOT + provided + + + com.celements + celements-config-source-api + 7.0-SNAPSHOT + provided + + + com.celements + celements-config-source + 7.0-SNAPSHOT + provided + + + com.celements + celements-observation + 7.0-SNAPSHOT + provided + + + com.celements + celements-xwiki-core + 7.0-SNAPSHOT + provided + + + com.celements + celements-xwiki-velocity + 7.0-SNAPSHOT + provided + + + com.celements + celements-servlet + 7.0-SNAPSHOT + provided + + + javax.servlet + javax.servlet-api + provided + + + struts + struts + + + + + org.springframework + spring-context + provided + + + org.springframework + spring-web + provided + + + + + commons-configuration + commons-configuration + + + commons-lang + commons-lang + provided + + + + + org.xwiki.platform + xwiki-core-properties + provided + + + org.xwiki.platform + xwiki-core-bridge + provided + + + org.xwiki.platform + xwiki-core-xml + provided + + + org.dom4j + dom4j + + + + + xerces + xercesImpl + provided + + + + + com.celements + celements-base-tests + 7.0-SNAPSHOT + test + + + com.celements + celements-shared-tests + 7.0-SNAPSHOT + test + + + junit + junit + + + + + org.easymock + easymock + test + + + + + org.xwiki.platform + xwiki-core-shared-tests + test + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + test-jar + + test-jar + + + + **/scaffolding/**.class + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + org/xwiki/rendering/syntax/Syntax.java, + org/xwiki/rendering/syntax/SyntaxType.java, + org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java, + org/xwiki/rendering/renderer/printer/XMLWikiPrinter.java, + org/xwiki/rendering/renderer/printer/VoidWikiPrinter.java, + org/xwiki/rendering/renderer/printer/LookaheadWikiPrinter.java, + org/xwiki/rendering/renderer/printer/WrappingWikiPrinter.java, + org/xwiki/rendering/listener/chaining/LookaheadChainingListener.java, + org/xwiki/rendering/listener/chaining/TextOnNewLineStateChainingListener.java, + org/xwiki/rendering/listener/chaining/EventType.java, + org/xwiki/rendering/listener/chaining/EmptyBlockChainingListener.java, + org/xwiki/rendering/listener/chaining/BlockStateChainingListener.java, + org/xwiki/rendering/listener/chaining/GroupStateChainingListener.java, + org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxMacroRenderer.java, + org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxChainingRenderer.java, + org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxEscapeHandler.java, + org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxImageRenderer.java, + org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxResourceRenderer.java, + org/xwiki/rendering/internal/renderer/plain/PlainTextRenderer.java, + org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRenderer.java, + org/xwiki/rendering/internal/renderer/printer/XHTMLWriter.java, + org/xwiki/rendering/internal/renderer/printer/XWikiSyntaxEscapeWikiPrinter.java, + org/xwiki/rendering/internal/renderer/printer/WikiWriter.java, + org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/link/DefaultXHTMLLinkRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLBlockRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/XHTMLMacroRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/XHTMLBlockRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/image/DefaultXHTMLImageRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/image/AnnotatedXHTMLImageRenderer.java, + org/xwiki/rendering/internal/renderer/event/EventsChainingRenderer.java, + org/xwiki/rendering/internal/renderer/event/EventRendererFactory.java, + org/xwiki/rendering/internal/renderer/event/EventBlockRenderer.java, + org/xwiki/rendering/internal/parser/XDOMGeneratorListener.java + + + + + + diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractBlock.java new file mode 100644 index 000000000..28b29b5f1 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractBlock.java @@ -0,0 +1,544 @@ +/* + * 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.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Implementation for Block operations. All blocks should extend this class. Supports the notion of + * generic parameters + * which can be added to a block (see {@link #getParameter(String)} for more details. + * + * @version $Id$ + * @since 1.5M2 + */ +public abstract class AbstractBlock implements Block { + + /** + * Store parameters, see {@link #getParameter(String)} for more explanations on what parameters + * are. + */ + private Map parameters = new LinkedHashMap(); + + /** + * The Blocks this Block contains. + */ + private List childrenBlocks = new ArrayList(); + + /** + * The Block containing this Block. + */ + private Block parentBlock; + + /** + * The next Sibling Block or null if no next sibling exists. + */ + private Block nextSiblingBlock; + + /** + * The previous Sibling Block or null if no previous sibling exists. + */ + private Block previousSiblingBlock; + + /** + * Empty constructor to construct an empty block. + */ + public AbstractBlock() { + // Nothing to do + } + + /** + * Construct a block with parameters. + * + * @param parameters + * the parameters to set + */ + public AbstractBlock(Map parameters) { + this.parameters.putAll(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#addChild(org.xwiki.rendering.block.Block) + */ + public void addChild(Block blockToAdd) { + insertChildAfter(blockToAdd, null); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#addChildren(java.util.List) + */ + public void addChildren(List blocksToAdd) { + for (Block blockToAdd : blocksToAdd) { + addChild(blockToAdd); + } + } + + /** + * {@inheritDoc} + * + * @see Block#setNextSiblingBlock(Block) + * @since 2.6RC1 + */ + public void setNextSiblingBlock(Block nextSiblingBlock) { + this.nextSiblingBlock = nextSiblingBlock; + } + + /** + * {@inheritDoc} + * + * @see Block#setPreviousSiblingBlock(Block) + * @since 2.6RC1 + */ + public void setPreviousSiblingBlock(Block previousSiblingBlock) { + this.previousSiblingBlock = previousSiblingBlock; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#insertChildBefore(org.xwiki.rendering.block.Block, + * org.xwiki.rendering.block.Block) + */ + public void insertChildBefore(Block blockToInsert, Block nextBlock) { + blockToInsert.setParent(this); + + if (nextBlock == null) { + // Last block becomes last but one + if (!this.childrenBlocks.isEmpty()) { + Block lastBlock = this.childrenBlocks.get(this.childrenBlocks.size() - 1); + blockToInsert.setPreviousSiblingBlock(lastBlock); + lastBlock.setNextSiblingBlock(blockToInsert); + } else { + blockToInsert.setPreviousSiblingBlock(null); + } + blockToInsert.setNextSiblingBlock(null); + this.childrenBlocks.add(blockToInsert); + } else { + // If there's a previous block to nextBlock then get it to set its next sibling + Block previousBlock = nextBlock.getPreviousSibling(); + if (previousBlock != null) { + previousBlock.setNextSiblingBlock(blockToInsert); + blockToInsert.setPreviousSiblingBlock(previousBlock); + } else { + blockToInsert.setPreviousSiblingBlock(null); + } + blockToInsert.setNextSiblingBlock(nextBlock); + nextBlock.setPreviousSiblingBlock(blockToInsert); + this.childrenBlocks.add(indexOfChild(nextBlock), blockToInsert); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#insertChildAfter(org.xwiki.rendering.block.Block, + * org.xwiki.rendering.block.Block) + */ + public void insertChildAfter(Block blockToInsert, Block previousBlock) { + if (previousBlock == null) { + insertChildBefore(blockToInsert, null); + } else { + // If there's a next block to previousBlock then get it to set its previous sibling + Block nextBlock = previousBlock.getNextSibling(); + if (nextBlock != null) { + nextBlock.setPreviousSiblingBlock(blockToInsert); + blockToInsert.setNextSiblingBlock(nextBlock); + } else { + blockToInsert.setNextSiblingBlock(null); + } + blockToInsert.setPreviousSiblingBlock(previousBlock); + previousBlock.setNextSiblingBlock(blockToInsert); + this.childrenBlocks.add(indexOfChild(previousBlock) + 1, blockToInsert); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#replaceChild(Block, Block) + */ + public void replaceChild(Block newBlock, Block oldBlock) { + replaceChild(Collections.singletonList(newBlock), oldBlock); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#replaceChild(List, Block) + */ + public void replaceChild(List newBlocks, Block oldBlock) { + int position = indexOfChild(oldBlock); + + if (position == -1) { + throw new InvalidParameterException("Provided Block to replace is not a child"); + } + + List 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 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 &#38;, since &apos; 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 and not since some browsers do not support the + // syntax (FF3) when the content type is set to HTML instead of XHTML. + getXHTMLWikiPrinter().printXMLStartElement("span", new String[][] { { "id", name } }); + getXHTMLWikiPrinter().printXMLEndElement("span"); + } else { + getXHTMLWikiPrinter().printXMLStartElement("div", new String[][] { { "id", name } }); + getXHTMLWikiPrinter().printXMLEndElement("div"); + } + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#onHorizontalLine(Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + getXHTMLWikiPrinter().printXMLElement("hr", parameters); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#onVerbatim(String, boolean, Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + if (isInline) { + // Note: We generate a tt element rather than a pre element since pre elements cannot be + // located inside + // paragraphs for example. There also no tag in XHTML that has a semantic of preserving inline + // content so + // tt is the closed to pre for inline. + // The class is what is expected by wikimodel to understand the tt as meaning a verbatim and + // not a Monospace + // element. + getXHTMLWikiPrinter().printXMLStartElement("tt", new String[][] { { "class", "wikimodel-verbatim" } }); + getXHTMLWikiPrinter().printXML(protectedString); + getXHTMLWikiPrinter().printXMLEndElement("tt"); + } else { + getXHTMLWikiPrinter().printXMLStartElement("pre", parameters); + getXHTMLWikiPrinter().printXML(protectedString); + getXHTMLWikiPrinter().printXMLEndElement("pre"); + } + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + // We need to use a special tag for empty lines since in XHTML the BR tag cannot be used outside + // of content + // tags. + // Note: We're using
and not
since some browsers do not support the
+ // syntax (FF3) + // when the content type is set to HTML instead of XHTML. + for (int i = 0; i < count; ++i) { + getXHTMLWikiPrinter().printXMLStartElement("div", new String[][] { { "class", "wikimodel-emptyline" } }); + getXHTMLWikiPrinter().printXMLEndElement("div"); + } + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + getXHTMLWikiPrinter().printXMLStartElement("dl", parameters); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + getXHTMLWikiPrinter().printXMLEndElement("dl"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + getXHTMLWikiPrinter().printXMLStartElement("dt"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + getXHTMLWikiPrinter().printXMLStartElement("dd"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + getXHTMLWikiPrinter().printXMLEndElement("dt"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + getXHTMLWikiPrinter().printXMLEndElement("dd"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + if (getBlockState().isInQuotationLine()) { + getXHTMLWikiPrinter().printXMLEndElement("p"); + } + + getXHTMLWikiPrinter().printXMLStartElement("blockquote", parameters); + + getXHTMLWikiPrinter().printXMLStartElement("p"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + getXHTMLWikiPrinter().printXMLEndElement("p"); + + getXHTMLWikiPrinter().printXMLEndElement("blockquote"); + + if (getBlockState().isInQuotationLine()) { + getXHTMLWikiPrinter().printXMLStartElement("p"); + } + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + // Send a new line if the previous event was endQuotationLine since we need to separate each + // quotation line + // or they'll printed next to each other and not on a new line each. + if (getBlockState().isInQuotation() && getBlockState().getPreviousEvent() == Event.QUOTATION_LINE) { + onNewLine(); + } + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + getXHTMLWikiPrinter().printXMLStartElement("table", parameters); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + getXHTMLWikiPrinter().printXMLStartElement("tr", parameters); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + getXHTMLWikiPrinter().printXMLStartElement("td", parameters); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + // Find proper scope attribute value + Map parametersWithScope; + if (!parameters.containsKey("scope")) { + parametersWithScope = new LinkedHashMap(parameters); + + if (getBlockState().getCellRow() == 0 || getBlockState().getCellCol() > 0) { + parametersWithScope.put("scope", "col"); + } else { + parametersWithScope.put("scope", "row"); + } + } else { + parametersWithScope = parameters; + } + + // Write th element + getXHTMLWikiPrinter().printXMLStartElement("th", parametersWithScope); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + getXHTMLWikiPrinter().printXMLEndElement("table"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + getXHTMLWikiPrinter().printXMLEndElement("tr"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + getXHTMLWikiPrinter().printXMLEndElement("td"); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + getXHTMLWikiPrinter().printXMLEndElement("th"); + } + + /** + * {@inheritDoc} + * + * @see 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) { + // Ensure the image renderer is using the latest printer since the original printer used could + // have been + // superseded by another one in the printer stack. + this.imageRenderer.setXHTMLWikiPrinter(getXHTMLWikiPrinter()); + this.imageRenderer.onImage(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#onRawText(String, Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + // Directly inject the HTML content in the wiki printer (bypassing the XHTML printer) + if ((syntax.getType() == SyntaxType.XHTML) || (syntax.getType() == SyntaxType.HTML)) { + getXHTMLWikiPrinter().printRaw(text); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLMacroRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLMacroRenderer.java new file mode 100644 index 000000000..a348255be --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLMacroRenderer.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.renderer.xhtml; + +import java.util.Map; + +import org.xwiki.rendering.internal.renderer.ParametersPrinter; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; + +/** + * Renders a XWiki Macro into Annotated XHTML (ie the macro definition is created as XHTML + * comments). + * + * @version $Id$ + * @since 1.7M2 + */ +public class XHTMLMacroRenderer { + + /** + * Character to separate Macro name, content and parameters in XHTML comments. + */ + private static final String COMMENT_SEPARATOR = "|-|"; + + private ParametersPrinter parametersPrinter = new ParametersPrinter(); + + public void render(XHTMLWikiPrinter printer, String name, Map parameters, String content) { + beginRender(printer, name, parameters, content); + endRender(printer); + } + + public void beginRender(XHTMLWikiPrinter printer, String name, Map parameters, String content) { + StringBuilder buffer = new StringBuilder("startmacro:"); + + // Print name + buffer.append(name); + + // Print parameters + buffer.append(COMMENT_SEPARATOR); + if (!parameters.isEmpty()) { + buffer.append(this.parametersPrinter.print(parameters, '\\')); + } + + // Print content + if (content != null) { + buffer.append(COMMENT_SEPARATOR); + buffer.append(content); + } + + printer.printXMLComment(buffer.toString(), true); + } + + public void endRender(XHTMLWikiPrinter printer) { + printer.printXMLComment("stopmacro"); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLMarkerResourceReferenceSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLMarkerResourceReferenceSerializer.java new file mode 100644 index 000000000..a73d7d727 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLMarkerResourceReferenceSerializer.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.internal.renderer.xhtml; + +import java.util.Map; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.internal.renderer.ParametersPrinter; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; + +/** + * Serialize a Resource Reference into XHTML comments using the syntax + * {@code (isTyped)|-|(type)|-|(reference)|-|(parameters: key="value")}. This is used for example to + * save a Link or + * Image Reference in XHTML Comment in the Annotated XHTML Renderer. + * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("xhtmlmarker") +public class XHTMLMarkerResourceReferenceSerializer implements ResourceReferenceSerializer { + + /** + * Character to separate Link reference and parameters in XHTML comments. + */ + private static final String COMMENT_SEPARATOR = "|-|"; + + /** + * Used to print Link Parameters in XHTML comments. + */ + private ParametersPrinter parametersPrinter = new ParametersPrinter(); + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer#serialize(ResourceReference) + */ + public String serialize(ResourceReference reference) { + StringBuilder buffer = new StringBuilder(); + + // Print if the Resource Reference is typed, the Resource Reference Type and the Reference + // itself + buffer.append(reference.isTyped()); + buffer.append(COMMENT_SEPARATOR); + buffer.append(reference.getType().getScheme()); + buffer.append(COMMENT_SEPARATOR); + buffer.append(reference.getReference()); + + // Print Resource Reference parameters. We need to do this so that the XHTML parser doesn't have + // to parse the query string to extract the parameters. Doing so could lead to false result + // since + // for example the XHTML renderer can add a parent parameter in the query string for links to + // non + // existing documents. + // + // Also note that we don't need to print Resource Reference parameters since they are added as + // XHTML class + // attributes by the XHTML Renderer and thus the XHTML parser will be able to get them again as + // attributes. + Map linkReferenceParameters = reference.getParameters(); + if (!linkReferenceParameters.isEmpty()) { + buffer.append(COMMENT_SEPARATOR); + buffer.append(this.parametersPrinter.print(linkReferenceParameters, '\\')); + } + + return buffer.toString(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java new file mode 100644 index 000000000..5c0539240 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java @@ -0,0 +1,83 @@ +/* + * 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.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.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; + +/** + * Generates XHTML from a {@link org.xwiki.rendering.block.XDOM} object being traversed. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("xhtml/1.0") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class XHTMLRenderer extends AbstractChainingPrintRenderer implements Initializable { + + /** + * 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. + */ + @Requirement + private XHTMLLinkRenderer linkRenderer; + + /** + * 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. + */ + @Requirement + private XHTMLImageRenderer imageRenderer; + + /** + * {@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 XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain)); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRendererFactory.java new file mode 100644 index 000000000..7dadbd714 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRendererFactory.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 XHTML Renderers. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("xhtml/1.0") +public class XHTMLRendererFactory extends AbstractPrintRendererFactory { + + /** + * {@inheritDoc} + * + * @see AbstractPrintRendererFactory#getSyntax() + */ + public Syntax getSyntax() { + return Syntax.XHTML_1_0; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/AnnotatedXHTMLImageRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/AnnotatedXHTMLImageRenderer.java new file mode 100644 index 000000000..96c5e1fa8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/AnnotatedXHTMLImageRenderer.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.xhtml.image; + +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.annotation.InstantiationStrategy; +import org.xwiki.component.descriptor.ComponentInstantiationStrategy; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; + +/** + * Render images as XHTML, using annotations (see + * {@link org.xwiki.rendering.internal.renderer.xhtml.AnnotatedXHTMLRenderer} for more details). + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("annotated") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class AnnotatedXHTMLImageRenderer implements XHTMLImageRenderer { + + /** + * Used to print Image reference as XHTML comments. + */ + @Requirement("xhtmlmarker") + private ResourceReferenceSerializer xhtmlMarkerSerializer; + + /** + * The default XHTML Link Renderer that we're wrapping. + */ + @Requirement + private XHTMLImageRenderer defaultImageRenderer; + + public void setXHTMLWikiPrinter(XHTMLWikiPrinter printer) { + this.defaultImageRenderer.setXHTMLWikiPrinter(printer); + } + + public XHTMLWikiPrinter getXHTMLWikiPrinter() { + return this.defaultImageRenderer.getXHTMLWikiPrinter(); + } + + /** + * {@inheritDoc} + * + * @see XHTMLImageRenderer#onImage(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + // We need to save the image location in XML comment so that it can be reconstructed later on + // when moving + // from XHTML to wiki syntax. + StringBuffer buffer = new StringBuffer("startimage:"); + buffer.append(this.xhtmlMarkerSerializer.serialize(reference)); + + getXHTMLWikiPrinter().printXMLComment(buffer.toString(), true); + this.defaultImageRenderer.onImage(reference, isFreeStandingURI, parameters); + getXHTMLWikiPrinter().printXMLComment("stopimage"); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/DefaultXHTMLImageRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/DefaultXHTMLImageRenderer.java new file mode 100644 index 000000000..66553fefb --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/DefaultXHTMLImageRenderer.java @@ -0,0 +1,162 @@ +/* + * 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.image; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.annotation.InstantiationStrategy; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.component.descriptor.ComponentInstantiationStrategy; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; +import org.xwiki.rendering.renderer.reference.link.URILabelGenerator; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; +import org.xwiki.rendering.wiki.WikiModel; + +/** + * Default implementation for rendering images as XHTML. We handle both cases: + *
    + *
  • when inside a wiki (ie when an implementation of {@link WikiModel} is provided.
  • + *
  • when outside of a wiki. In this case we only handle external images and document images don't + * display + * anything.
  • + *
+ * + * @version $Id$ + * @since 2.0M3 + */ +@Component +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class DefaultXHTMLImageRenderer implements XHTMLImageRenderer, Initializable { + + /** + * @see #setXHTMLWikiPrinter(XHTMLWikiPrinter) + */ + private XHTMLWikiPrinter xhtmlPrinter; + + /** + * Use to resolve local image URL when the image is attached to a document. + */ + private WikiModel wikiModel; + + @Requirement + private ComponentManager componentManager; + + /** + * {@inheritDoc} + * + * @see Initializable#initialize() + */ + public void initialize() throws InitializationException { + // Try to find a WikiModel implementation and set it if it can be found. If not it means we're + // in + // non wiki mode (i.e. no attachment in wiki documents and no links to documents for example). + try { + this.wikiModel = this.componentManager.lookup(WikiModel.class); + } catch (ComponentLookupException e) { + // There's no WikiModel implementation available. this.wikiModel stays null. + } + } + + /** + * {@inheritDoc} + * + * @see XHTMLImageRenderer#setXHTMLWikiPrinter(XHTMLWikiPrinter) + */ + public void setXHTMLWikiPrinter(XHTMLWikiPrinter printer) { + this.xhtmlPrinter = printer; + } + + /** + * {@inheritDoc} + * + * @see XHTMLImageRenderer#getXHTMLWikiPrinter() + */ + public XHTMLWikiPrinter getXHTMLWikiPrinter() { + return this.xhtmlPrinter; + } + + /** + * {@inheritDoc} + * + * @see XHTMLImageRenderer#onImage(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + Map attributes = new LinkedHashMap(); + + // First we need to compute the image URL. + String imageURL; + if (reference.getType().equals(ResourceType.ATTACHMENT) || reference.getType().equals(ResourceType.ICON)) { + // Note if wikiModel is null then all Image reference objects will be of type URL. This must + // be ensured by + // the Image Reference parser used beforehand. However we're adding a protection here against + // Image + // Reference parsers that would not honor this contract... + if (this.wikiModel != null) { + imageURL = this.wikiModel.getImageURL(reference, parameters); + } else { + throw new RuntimeException("Invalid Image type. In non wiki mode, all image types must be URL images."); + } + } else { + imageURL = reference.getReference(); + } + + // Then add it as an attribute of the IMG element. + attributes.put(SRC, imageURL); + + // Add the class if we're on a freestanding uri + if (isFreeStandingURI) { + attributes.put("class", "wikimodel-freestanding"); + } + + // Add the other parameters as attributes + attributes.putAll(parameters); + + // If no ALT attribute has been specified, add it since the XHTML specifications makes it + // mandatory. + if (!parameters.containsKey(ALTERNATE)) { + attributes.put(ALTERNATE, computeAltAttributeValue(reference)); + } + + // And generate the XHTML IMG element. + getXHTMLWikiPrinter().printXMLElement(IMG, attributes); + } + + private String computeAltAttributeValue(ResourceReference reference) { + String label; + try { + URILabelGenerator uriLabelGenerator = this.componentManager.lookup(URILabelGenerator.class, + reference.getType().getScheme()); + label = uriLabelGenerator.generateLabel(reference); + } catch (ComponentLookupException e) { + label = reference.getReference(); + } + return label; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/XHTMLImageRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/XHTMLImageRenderer.java new file mode 100644 index 000000000..65c930428 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/image/XHTMLImageRenderer.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.internal.renderer.xhtml.image; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.ImageListener; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; + +/** + * Renders images as XHTML. + * + * @version $Id$ + * @since 1.8RC3 + */ +@ComponentRole +public interface XHTMLImageRenderer extends ImageListener { + + /** + * The name of the XHTML image element. + */ + String IMG = "img"; + + /** + * img XHTML element parameter to indicate an alternate description to the image. + */ + String ALTERNATE = "alt"; + + /** + * img XHTML element parameter to indicate where the image is located. + */ + String SRC = "src"; + + /** + * @param printer + * the XHTML printer to use to output images as XHTML + */ + void setXHTMLWikiPrinter(XHTMLWikiPrinter printer); + + /** + * @return the XHTML printer to use to output images as XHTML + * @since 2.0M3 + */ + XHTMLWikiPrinter getXHTMLWikiPrinter(); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AbstractXHTMLLinkTypeRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AbstractXHTMLLinkTypeRenderer.java new file mode 100644 index 000000000..237ed9bc1 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AbstractXHTMLLinkTypeRenderer.java @@ -0,0 +1,184 @@ +/* + * 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.link; + +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.renderer.reference.link.URILabelGenerator; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Common code for XHTML Link Type Renderer implementations. + * + * @version $Id$ + * @since 2.5M2 + */ +public abstract class AbstractXHTMLLinkTypeRenderer implements XHTMLLinkTypeRenderer { + + /** + * The XHTML element class parameter. + */ + protected static final String CLASS = "class"; + + /** + * The name of the XHTML format element. + */ + protected static final String SPAN = "span"; + + /** + * Used to look for {@link org.xwiki.rendering.renderer.reference.link.URILabelGenerator} + * component implementations + * when computing labels. + */ + @Requirement + protected ComponentManager componentManager; + + /** + * The XHTML printer to use to output links as XHTML. + */ + private XHTMLWikiPrinter xhtmlPrinter; + + /** + * @see #setHasLabel(boolean) + */ + private boolean hasLabel; + + /** + * @return See {@link #setHasLabel(boolean)} + */ + protected boolean hasLabel() { + return this.hasLabel; + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkTypeRenderer#setHasLabel(boolean) + */ + public void setHasLabel(boolean hasLabel) { + this.hasLabel = hasLabel; + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkTypeRenderer#setXHTMLWikiPrinter(org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter) + */ + public void setXHTMLWikiPrinter(XHTMLWikiPrinter printer) { + this.xhtmlPrinter = printer; + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkTypeRenderer#getXHTMLWikiPrinter() + */ + public XHTMLWikiPrinter getXHTMLWikiPrinter() { + return this.xhtmlPrinter; + } + + /** + * Hook called when rendering the beginning of a link to allow implementation classes to augment + * the passed span and + * anchor attributes as they see fit. + * + * @param reference + * the reference of the link being rendered + * @param spanAttributes + * the HTML attributes for the SPAN HTML element added around the ANCHOR HTML element + * @param anchorAttributes + * the HTML attributes for the ANCHOR element + */ + protected abstract void beginLinkExtraAttributes(ResourceReference reference, Map spanAttributes, + Map anchorAttributes); + + /** + * Default implementation for computing a link label when no label has been specified. Can be + * overwritten by + * implementations to provide a different algorithm. + * + * @param reference + * the reference of the link for which to compute the label + * @return the computed label + */ + protected String computeLabel(ResourceReference reference) { + // Look for a component implementing URILabelGenerator with a role hint matching the link + // scheme. + // If not found then use the full reference as the label. + // If there's no scheme separator then use the full reference as the label. Note that this can + // happen + // when we're not in wiki mode (since all links are considered URIs when not in wiki mode). + String label; + try { + URILabelGenerator uriLabelGenerator = this.componentManager.lookup(URILabelGenerator.class, + reference.getType().getScheme()); + label = uriLabelGenerator.generateLabel(reference); + } catch (ComponentLookupException e) { + label = reference.getReference(); + } + return label; + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkTypeRenderer# + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + Map spanAttributes = new LinkedHashMap(); + Map anchorAttributes = new LinkedHashMap(); + + // Add all parameters to the A attributes + anchorAttributes.putAll(parameters); + + spanAttributes.put(CLASS, "wikiexternallink"); + if (isFreeStandingURI) { + anchorAttributes.put(CLASS, "wikimodel-freestanding"); + } + + beginLinkExtraAttributes(reference, spanAttributes, anchorAttributes); + + getXHTMLWikiPrinter().printXMLStartElement(SPAN, spanAttributes); + getXHTMLWikiPrinter().printXMLStartElement(XHTMLLinkRenderer.ANCHOR, anchorAttributes); + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#endLink(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, Map) + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + // If there was no link content then generate it based on the passed reference + if (!hasLabel()) { + getXHTMLWikiPrinter().printXMLStartElement(SPAN, new String[][] { { CLASS, "wikigeneratedlinkcontent" } }); + getXHTMLWikiPrinter().printXML(computeLabel(reference)); + getXHTMLWikiPrinter().printXMLEndElement(SPAN); + } + + getXHTMLWikiPrinter().printXMLEndElement(XHTMLLinkRenderer.ANCHOR); + getXHTMLWikiPrinter().printXMLEndElement(SPAN); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AnnotatedXHTMLLinkRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AnnotatedXHTMLLinkRenderer.java new file mode 100644 index 000000000..a65d73578 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AnnotatedXHTMLLinkRenderer.java @@ -0,0 +1,112 @@ +/* + * 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.link; + +import java.util.Map; + +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.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; + +/** + * Render links as XHTML, using annotations (see + * {@link org.xwiki.rendering.internal.renderer.xhtml.AnnotatedXHTMLRenderer} for more details). + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("annotated") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class AnnotatedXHTMLLinkRenderer implements XHTMLLinkRenderer { + + /** + * Used to print Image reference as XHTML comments. + */ + @Requirement("xhtmlmarker") + private ResourceReferenceSerializer xhtmlMarkerSerializer; + + /** + * The default XHTML Link Renderer that we're wrapping. + */ + @Requirement + private XHTMLLinkRenderer defaultLinkRenderer; + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#setXHTMLWikiPrinter(org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter) + */ + public void setXHTMLWikiPrinter(XHTMLWikiPrinter printer) { + this.defaultLinkRenderer.setXHTMLWikiPrinter(printer); + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#setHasLabel(boolean) + */ + public void setHasLabel(boolean hasLabel) { + this.defaultLinkRenderer.setHasLabel(hasLabel); + } + + /** + * {@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) { + // Add an XML comment as a placeholder so that the XHTML parser can find the document name. + // Otherwise it would be too difficult to transform a URL into a document name especially since + // a link can refer to an external URL. + StringBuffer buffer = new StringBuffer("startwikilink:"); + buffer.append(this.xhtmlMarkerSerializer.serialize(reference)); + + getXHTMLWikiPrinter().printXMLComment(buffer.toString(), true); + this.defaultLinkRenderer.beginLink(reference, isFreeStandingURI, 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.defaultLinkRenderer.endLink(reference, isFreeStandingURI, parameters); + + // Add a XML comment to signify the end of the link. + getXHTMLWikiPrinter().printXMLComment("stopwikilink"); + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#getXHTMLWikiPrinter() + */ + public XHTMLWikiPrinter getXHTMLWikiPrinter() { + return this.defaultLinkRenderer.getXHTMLWikiPrinter(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AttachmentXHTMLLinkTypeRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AttachmentXHTMLLinkTypeRenderer.java new file mode 100644 index 000000000..2c0ba1a4f --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/AttachmentXHTMLLinkTypeRenderer.java @@ -0,0 +1,91 @@ +/* + * 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.link; + +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.manager.ComponentLookupException; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer; +import org.xwiki.rendering.wiki.WikiModel; + +import java.util.Map; + +/** + * Handle XHTML rendering for links to attachments. + * + * @version $Id$ + * @since 2.5M2 + */ +@Component("attach") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class AttachmentXHTMLLinkTypeRenderer extends AbstractXHTMLLinkTypeRenderer implements Initializable { + + /** + * Used to serialize the attachment link to XWiki Syntax 2.0 when we're not inside a wiki. We + * choose the XWiki + * Syntax 2.0 arbitrarily. Normally the user should never use a link to an attachment when not + * inside a wiki. + */ + @Requirement("xwiki/2.0") + private ResourceReferenceTypeSerializer defaultResourceReferenceTypeSerializer; + + /** + * Used to generate the link targeting a local document. + */ + private WikiModel wikiModel; + + /** + * {@inheritDoc} + * + * @see Initializable#initialize() + */ + public void initialize() throws InitializationException { + // Try to find a WikiModel implementation and set it if it can be found. If not it means we're + // in + // non wiki mode (i.e. no attachment in wiki documents and no links to documents for example). + try { + this.wikiModel = this.componentManager.lookup(WikiModel.class); + } catch (ComponentLookupException e) { + // There's no WikiModel implementation available. this.wikiModel stays null. + } + } + + /** + * {@inheritDoc} + * + * @see AbstractXHTMLLinkTypeRenderer#beginLinkExtraAttributes(org.xwiki.rendering.listener.reference.ResourceReference + * , java.util.Map, java.util.Map) + */ + @Override + protected void beginLinkExtraAttributes(ResourceReference reference, Map spanAttributes, + Map anchorAttributes) { + if (this.wikiModel != null) { + anchorAttributes.put(XHTMLLinkRenderer.HREF, this.wikiModel.getLinkURL(reference)); + } else { + anchorAttributes.put(XHTMLLinkRenderer.HREF, + this.defaultResourceReferenceTypeSerializer.serialize(reference)); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DefaultXHTMLLinkRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DefaultXHTMLLinkRenderer.java new file mode 100644 index 000000000..7e010faa8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DefaultXHTMLLinkRenderer.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.internal.renderer.xhtml.link; + +import java.util.Map; + +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.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; + +/** + * Default implementation for rendering links as XHTML. The implementation is pluggable in the sense + * that the + * implementation is done by + * {@link org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkTypeRenderer} + * implementation, each in charge of handling a given + * {@link org.xwiki.rendering.listener.reference.ResourceType}. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class DefaultXHTMLLinkRenderer implements XHTMLLinkRenderer { + + @Requirement + private XHTMLLinkTypeRenderer defaultLinkTypeRenderer; + + @Requirement + protected ComponentManager componentManager; + + /** + * The XHTML printer to use to output links as XHTML. + */ + private XHTMLWikiPrinter xhtmlPrinter; + + /** + * @see #setHasLabel(boolean) + */ + private boolean hasLabel; + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#setHasLabel(boolean) + */ + public void setHasLabel(boolean hasLabel) { + this.hasLabel = hasLabel; + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#setXHTMLWikiPrinter(XHTMLWikiPrinter) + */ + public void setXHTMLWikiPrinter(XHTMLWikiPrinter printer) { + this.xhtmlPrinter = printer; + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#getXHTMLWikiPrinter() + */ + public XHTMLWikiPrinter getXHTMLWikiPrinter() { + return this.xhtmlPrinter; + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#beginLink(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, Map) + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + getXHTMLLinkTypeRenderer(reference).beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkRenderer#endLink(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, Map) + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + getXHTMLLinkTypeRenderer(reference).endLink(reference, isFreeStandingURI, parameters); + } + + private XHTMLLinkTypeRenderer getXHTMLLinkTypeRenderer(ResourceReference reference) { + XHTMLLinkTypeRenderer renderer; + + // TODO: This is probably not very performant since it's called at each begin/endLink. + try { + renderer = this.componentManager.lookup(XHTMLLinkTypeRenderer.class, reference.getType().getScheme()); + } catch (ComponentLookupException e) { + // There's no specific XHTML Link Type Renderer for the passed link type, use the default + // renderer. + renderer = this.defaultLinkTypeRenderer; + } + renderer.setHasLabel(this.hasLabel); + renderer.setXHTMLWikiPrinter(getXHTMLWikiPrinter()); + return renderer; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DefaultXHTMLLinkTypeRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DefaultXHTMLLinkTypeRenderer.java new file mode 100644 index 000000000..b17cdab39 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DefaultXHTMLLinkTypeRenderer.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.renderer.xhtml.link; + +import java.util.Map; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.InstantiationStrategy; +import org.xwiki.component.descriptor.ComponentInstantiationStrategy; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Handle XHTML rendering for links for which we haven't found a specific + * {@link org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkTypeRenderer} implementation. + * + * @version $Id$ + * @since 2.5M2 + */ +@Component +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class DefaultXHTMLLinkTypeRenderer extends AbstractXHTMLLinkTypeRenderer { + + /** + * {@inheritDoc} + * + * @see AbstractXHTMLLinkTypeRenderer#beginLinkExtraAttributes(org.xwiki.rendering.listener.reference.ResourceReference + * , java.util.Map, java.util.Map) + */ + @Override + protected void beginLinkExtraAttributes(ResourceReference reference, Map spanAttributes, + Map anchorAttributes) { + anchorAttributes.put(XHTMLLinkRenderer.HREF, reference.getReference()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DocumentXHTMLLinkTypeRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DocumentXHTMLLinkTypeRenderer.java new file mode 100644 index 000000000..eb0988177 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/DocumentXHTMLLinkTypeRenderer.java @@ -0,0 +1,179 @@ +/* + * 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.link; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +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.manager.ComponentLookupException; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.rendering.listener.reference.DocumentResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator; +import org.xwiki.rendering.wiki.WikiModel; + +/** + * Handle XHTML rendering for links to documents. + * + * @version $Id$ + * @since 2.5M2 + */ +@Component("doc") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class DocumentXHTMLLinkTypeRenderer extends AbstractXHTMLLinkTypeRenderer implements Initializable { + + /** + * The class attribute 'wikilink'. + */ + private static final String WIKILINK = "wikilink"; + + /** + * Used to generate the link targeting a local document. + */ + private WikiModel wikiModel; + + /** + * Used to generate a link label. + */ + @Requirement + private LinkLabelGenerator linkLabelGenerator; + + /** + * {@inheritDoc} + * + * @see Initializable#initialize() + */ + public void initialize() throws InitializationException { + // Try to find a WikiModel implementation and set it if it can be found. If not it means we're + // in + // non wiki mode (i.e. no attachment in wiki documents and no links to documents for example). + try { + this.wikiModel = this.componentManager.lookup(WikiModel.class); + } catch (ComponentLookupException e) { + // There's no WikiModel implementation available. this.wikiModel stays null. + } + } + + /** + * {@inheritDoc} + * + * @see XHTMLLinkTypeRenderer#beginLink(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, Map) + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + if (this.wikiModel == null) { + super.beginLink(reference, isFreeStandingURI, parameters); + } else { + beginInternalLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see AbstractXHTMLLinkTypeRenderer#computeLabel(org.xwiki.rendering.listener.reference.ResourceReference) + */ + @Override + protected String computeLabel(ResourceReference reference) { + return this.linkLabelGenerator.generate(reference); + } + + /** + * {@inheritDoc} + * + * @see AbstractXHTMLLinkTypeRenderer#beginLinkExtraAttributes(org.xwiki.rendering.listener.reference.ResourceReference + * , java.util.Map, java.util.Map) + */ + @Override + protected void beginLinkExtraAttributes(ResourceReference reference, Map spanAttributes, + Map anchorAttributes) { + if (StringUtils.isEmpty(reference.getReference())) { + renderAutoLink(reference, spanAttributes, anchorAttributes); + } else { + anchorAttributes.put(XHTMLLinkRenderer.HREF, reference.getReference()); + } + } + + /** + * Start of an internal link. + * + * @param reference + * the reference to the link + * @param isFreeStandingURI + * if true then the link is a free standing URI directly in the text + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + private void beginInternalLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + Map spanAttributes = new LinkedHashMap(); + Map anchorAttributes = new LinkedHashMap(); + + // Add all parameters to the A attributes + anchorAttributes.putAll(parameters); + + if (StringUtils.isEmpty(reference.getReference())) { + renderAutoLink(reference, spanAttributes, anchorAttributes); + } else if (this.wikiModel.isDocumentAvailable(reference)) { + spanAttributes.put(CLASS, WIKILINK); + anchorAttributes.put(XHTMLLinkRenderer.HREF, this.wikiModel.getDocumentViewURL(reference)); + } else { + // The wiki document doesn't exist + spanAttributes.put(CLASS, "wikicreatelink"); + anchorAttributes.put(XHTMLLinkRenderer.HREF, this.wikiModel.getDocumentEditURL(reference)); + } + + getXHTMLWikiPrinter().printXMLStartElement(SPAN, spanAttributes); + getXHTMLWikiPrinter().printXMLStartElement(XHTMLLinkRenderer.ANCHOR, anchorAttributes); + } + + /** + * @param reference + * the reference to the link + * @param spanAttributes + * the span element where to put the class + * @param aAttributes + * the anchor element where to put the reference + */ + private void renderAutoLink(ResourceReference reference, Map spanAttributes, + Map aAttributes) { + spanAttributes.put(CLASS, WIKILINK); + + StringBuilder buffer = new StringBuilder(); + String queryString = reference.getParameter(DocumentResourceReference.QUERY_STRING); + if (queryString != null) { + buffer.append('?'); + buffer.append(queryString); + } + buffer.append('#'); + String anchor = reference.getParameter(DocumentResourceReference.ANCHOR); + if (anchor != null) { + buffer.append(anchor); + } + + aAttributes.put(XHTMLLinkRenderer.HREF, buffer.toString()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/InterWikiXHTMLLinkTypeRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/InterWikiXHTMLLinkTypeRenderer.java new file mode 100644 index 000000000..bc7a38dfe --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/InterWikiXHTMLLinkTypeRenderer.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.xhtml.link; + +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.rendering.configuration.RenderingConfiguration; +import org.xwiki.rendering.listener.reference.InterWikiResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; + +import java.util.Map; +import java.util.Properties; + +/** + * Handle XHTML rendering for interwiki links. + * + * @version $Id$ + * @since 2.5M2 + */ +@Component("interwiki") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class InterWikiXHTMLLinkTypeRenderer extends AbstractXHTMLLinkTypeRenderer { + + /** + * Used to get access to the InterWiki definitions. + */ + @Requirement + private RenderingConfiguration renderingConfiguration; + + /** + * {@inheritDoc} + * + * @see AbstractXHTMLLinkTypeRenderer#beginLinkExtraAttributes(org.xwiki.rendering.listener.reference.ResourceReference + * , java.util.Map, java.util.Map) + */ + @Override + protected void beginLinkExtraAttributes(ResourceReference reference, Map spanAttributes, + Map anchorAttributes) { + // Look for an InterWiki definition for the passed Link. If not found then simply use the + // InterWiki Path. + String interWikiAlias = reference.getParameter(InterWikiResourceReference.INTERWIKI_ALIAS); + Properties definitions = this.renderingConfiguration.getInterWikiDefinitions(); + if (definitions.containsKey(interWikiAlias)) { + anchorAttributes.put(XHTMLLinkRenderer.HREF, + definitions.getProperty(interWikiAlias) + reference.getReference()); + } else { + anchorAttributes.put(XHTMLLinkRenderer.HREF, reference.getReference()); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/MailtoXHTMLLinkTypeRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/MailtoXHTMLLinkTypeRenderer.java new file mode 100644 index 000000000..61e7a8892 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/MailtoXHTMLLinkTypeRenderer.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.internal.renderer.xhtml.link; + +import java.util.Map; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.InstantiationStrategy; +import org.xwiki.component.descriptor.ComponentInstantiationStrategy; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Handle XHTML rendering for mailto links. + * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("mailto") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class MailtoXHTMLLinkTypeRenderer extends AbstractXHTMLLinkTypeRenderer { + + /** + * {@inheritDoc} + * + * @see AbstractXHTMLLinkTypeRenderer#beginLinkExtraAttributes(ResourceReference, java.util.Map, + * java.util.Map) + */ + @Override + protected void beginLinkExtraAttributes(ResourceReference reference, Map spanAttributes, + Map anchorAttributes) { + anchorAttributes.put(XHTMLLinkRenderer.HREF, reference.getType().getScheme() + ':' + reference.getReference()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/UNCXHTMLLinkTypeRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/UNCXHTMLLinkTypeRenderer.java new file mode 100644 index 000000000..ab2c5bd22 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/UNCXHTMLLinkTypeRenderer.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.xhtml.link; + +import java.util.Map; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.InstantiationStrategy; +import org.xwiki.component.descriptor.ComponentInstantiationStrategy; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Handle XHTML rendering for UNC links (Universal Naming Convention). + * + * @version $Id$ + * @since 2.7M1 + */ +@Component("unc") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class UNCXHTMLLinkTypeRenderer extends AbstractXHTMLLinkTypeRenderer { + + /** + * {@inheritDoc} + * + * @see AbstractXHTMLLinkTypeRenderer#beginLinkExtraAttributes(ResourceReference, java.util.Map, + * java.util.Map) + */ + @Override + protected void beginLinkExtraAttributes(ResourceReference reference, Map spanAttributes, + Map anchorAttributes) { + // Transform the UNC reference into a file URL of the format: + // file://///myserver/myshare/mydoc.txt + // i.e. replace all "\" chars by "/" and prefix with "file:///". + String fileURL = "file:///" + reference.getReference().replaceAll("\\\\", "/"); + + anchorAttributes.put(XHTMLLinkRenderer.HREF, fileURL); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/XHTMLLinkRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/XHTMLLinkRenderer.java new file mode 100644 index 000000000..53453a6b0 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/XHTMLLinkRenderer.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.xhtml.link; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.LinkListener; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; + +/** + * Renders links as XHTML. + * + * @version $Id$ + * @since 1.8RC3 + */ +@ComponentRole +public interface XHTMLLinkRenderer extends LinkListener { + + /** + * The name of the XHTML anchor element. + */ + String ANCHOR = "a"; + + /** + * The name of the XHTML anchor element reference parameter. + */ + String HREF = "href"; + + /** + * @param printer + * the XHTML printer to use to output links as XHTML + */ + void setXHTMLWikiPrinter(XHTMLWikiPrinter printer); + + /** + * @return the XHTML printer to use to output links as XHTML + * @since 2.0M3 + */ + XHTMLWikiPrinter getXHTMLWikiPrinter(); + + /** + * @param hasLabel + * true if the link to be rendered has a label specified or false otherwise. If no label + * has been + * specified then it's up to the XHTML renderer implementation to generate a default + * label. + */ + void setHasLabel(boolean hasLabel); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/XHTMLLinkTypeRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/XHTMLLinkTypeRenderer.java new file mode 100644 index 000000000..1795b2c95 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/XHTMLLinkTypeRenderer.java @@ -0,0 +1,67 @@ +/* + * 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.link; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.LinkListener; +import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter; + +/** + * Renders a type of link (mailto link, document link, URL, etc) in XHTML. Components implementing + * this interface + * implement the rendering logic only for a single link type and must have a role hint value equal + * to the + * {@link org.xwiki.rendering.listener.reference.ResourceType} name (eg "doc" for document link, + * "attach" for attachment + * link, etc). Implementations must handle both cases when rendering a link: + *
    + *
  • when inside a wiki (ie when an implementation of {@link org.xwiki.rendering.wiki.WikiModel} + * is provided.
  • + *
  • when outside of a wiki. In this case links to attachmets or documents are ignored and + * rendered as is as direct + * HREF values. In other words only external links are meaningful.
  • + *
+ * + * @version $Id$ + * @since 2.5M2 + */ +@ComponentRole +public interface XHTMLLinkTypeRenderer extends LinkListener { + + /** + * @param printer + * the XHTML printer to use to output links as XHTML + */ + void setXHTMLWikiPrinter(XHTMLWikiPrinter printer); + + /** + * @return the XHTML printer to use to output links as XHTML + */ + XHTMLWikiPrinter getXHTMLWikiPrinter(); + + /** + * @param hasLabel + * true if the link to be rendered has a label specified or false otherwise. If no label + * has been + * specified then it's up to the XHTML renderer implementation to generate a default + * label. + */ + void setHasLabel(boolean hasLabel); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/AbstractXWikiSyntaxRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/AbstractXWikiSyntaxRenderer.java new file mode 100644 index 000000000..d86d6c37e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/AbstractXWikiSyntaxRenderer.java @@ -0,0 +1,74 @@ +/* + * 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.xwiki20; + +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.ChainingListener; +import org.xwiki.rendering.listener.chaining.ConsecutiveNewLineStateChainingListener; +import org.xwiki.rendering.listener.chaining.GroupStateChainingListener; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.listener.chaining.LookaheadChainingListener; +import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer; + +/** + * XWiki Syntax Renderer implementation common to XWiki Syntax versions greater than 2.0 (X>iki + * Syntax 2.0, XWiki Syntax + * 2.1, etc). + * + * @version $Id$ + * @since 2.5M2 + */ +public abstract class AbstractXWikiSyntaxRenderer extends AbstractChainingPrintRenderer implements Initializable { + + /** + * Allows extending classes to choose which implementation to use. + * + * @param chain + * the rendering chain, see {@link org.xwiki.rendering.listener.chaining.ListenerChain} + * @return the XWiki Syntax renderer containing the implementation to use for handling the + * listener's events + */ + protected abstract ChainingListener createXWikiSyntaxChainingRenderer(ListenerChain chain); + + /** + * {@inheritDoc} + * + * @see Initializable#initialize() + */ + public void initialize() throws InitializationException { + ListenerChain chain = new XWikiSyntaxListenerChain(); + setListenerChain(chain); + + // Construct the listener chain in the right order. Listeners early in the chain are called + // before listeners + // placed later in the chain. This chain allows using several listeners that make it easier + // to write the XWiki Syntax chaining listener, for example for saving states (are we in a list, + // in a + // paragraph, are we starting a new line, etc). + chain.addListener(this); + chain.addListener(new LookaheadChainingListener(chain, 2)); + chain.addListener(new GroupStateChainingListener(chain)); + chain.addListener(new BlockStateChainingListener(chain)); + chain.addListener(new ConsecutiveNewLineStateChainingListener(chain)); + chain.addListener(createXWikiSyntaxChainingRenderer(chain)); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/AbstractXWikiSyntaxResourceRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/AbstractXWikiSyntaxResourceRenderer.java new file mode 100644 index 000000000..cc34e9959 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/AbstractXWikiSyntaxResourceRenderer.java @@ -0,0 +1,7 @@ +package org.xwiki.rendering.internal.renderer.xwiki20; + +/** + * @version $Id$ + * @since 2.5RC1 + */ +public abstract class AbstractXWikiSyntaxResourceRenderer {} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxBlockRenderer.java new file mode 100644 index 000000000..64a4471e1 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxBlockRenderer.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.internal.renderer.xwiki20; + +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; + +/** + * Renders a {@link org.xwiki.rendering.block.Block} in XWiki Syntax 2.0. + * + * @version $Id$ + */ +@Component("xwiki/2.0") +public class XWikiSyntaxBlockRenderer extends AbstractBlockRenderer { + + /** + * @see #getPrintRendererFactory() + */ + @Requirement("xwiki/2.0") + private PrintRendererFactory xwikiSyntaxRendererFactory; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.internal.renderer.AbstractBlockRenderer#getPrintRendererFactory() + */ + @Override + protected PrintRendererFactory getPrintRendererFactory() { + return this.xwikiSyntaxRendererFactory; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxChainingRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxChainingRenderer.java new file mode 100644 index 000000000..995df6981 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxChainingRenderer.java @@ -0,0 +1,924 @@ +/* + * 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.xwiki20; + +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.rendering.internal.renderer.printer.XWikiSyntaxEscapeWikiPrinter; +import org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxResourceRenderer; +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.ListenerChain; +import org.xwiki.rendering.listener.chaining.StackableChainingListener; +import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; +import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter; +import org.xwiki.rendering.renderer.printer.VoidWikiPrinter; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * Convert listener events to XWiki Syntax 2.0 output. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class XWikiSyntaxChainingRenderer extends AbstractChainingPrintRenderer implements StackableChainingListener { + + private XWikiSyntaxResourceRenderer linkResourceRenderer; + + private XWikiSyntaxResourceRenderer imageResourceRenderer; + + private XWikiSyntaxMacroRenderer macroPrinter; + + private ResourceReferenceSerializer linkReferenceSerializer; + + private ResourceReferenceSerializer imageReferenceSerializer; + + // Custom States + + private boolean isFirstElementRendered = false; + + private StringBuffer listStyle = new StringBuffer(); + + private Map previousFormatParameters; + + /** + * @since 2.5RC1 + */ + public XWikiSyntaxChainingRenderer(ListenerChain listenerChain, ResourceReferenceSerializer linkReferenceSerializer, + ResourceReferenceSerializer imageReferenceSerializer) { + setListenerChain(listenerChain); + + this.linkReferenceSerializer = linkReferenceSerializer; + this.imageReferenceSerializer = imageReferenceSerializer; + this.linkResourceRenderer = createXWikiSyntaxLinkRenderer(getListenerChain(), linkReferenceSerializer); + this.imageResourceRenderer = createXWikiSyntaxImageRenderer(getListenerChain(), imageReferenceSerializer); + this.macroPrinter = new XWikiSyntaxMacroRenderer(); + } + + /** + * @since 2.5RC1 + */ + protected XWikiSyntaxResourceRenderer createXWikiSyntaxLinkRenderer(ListenerChain listenerChain, + ResourceReferenceSerializer linkReferenceSerializer) { + return new XWikiSyntaxResourceRenderer((XWikiSyntaxListenerChain) listenerChain, linkReferenceSerializer); + } + + /** + * @since 2.5RC1 + */ + protected XWikiSyntaxResourceRenderer createXWikiSyntaxImageRenderer(ListenerChain listenerChain, + ResourceReferenceSerializer imageReferenceSerializer) { + return new XWikiSyntaxResourceRenderer((XWikiSyntaxListenerChain) listenerChain, imageReferenceSerializer); + } + + // State + + private BlockStateChainingListener getBlockState() { + return getXWikiSyntaxListenerChain().getBlockStateChainingListener(); + } + + /** + * {@inheritDoc} + * + * @see StackableChainingListener#createChainingListenerInstance() + */ + public StackableChainingListener createChainingListenerInstance() { + XWikiSyntaxChainingRenderer renderer = new XWikiSyntaxChainingRenderer(getListenerChain(), + this.linkReferenceSerializer, this.imageReferenceSerializer); + renderer.setPrinter(getPrinter()); + return renderer; + } + + private XWikiSyntaxListenerChain getXWikiSyntaxListenerChain() { + return (XWikiSyntaxListenerChain) getListenerChain(); + } + + private XWikiSyntaxResourceRenderer getLinkRenderer() { + return this.linkResourceRenderer; + } + + private XWikiSyntaxResourceRenderer getImageRenderer() { + return this.imageResourceRenderer; + } + + private XWikiSyntaxMacroRenderer getMacroPrinter() { + return this.macroPrinter; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map) + */ + @Override + public void beginGroup(Map parameters) { + if (!getBlockState().isInLine()) { + printEmptyLine(); + } + + if (parameters.size() > 0) { + printParameters(parameters, true); + } + + print("((("); + print("\n"); + + // Create a new listener stack in order to preserve current states, to handle the group. + getListenerChain().pushAllStackableListeners(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + // Ensure that all data in the escape printer have been flushed + getXWikiPrinter().flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map) + */ + @Override + public void endGroup(Map parameters) { + print("\n"); + print(")))"); + + // Restore previous listeners that were stacked + getListenerChain().popAllStackableListeners(); + } + + /** + * {@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) { + // Flush test content before the link. + // TODO: improve the block state renderer to be able to make the difference between what is + // bufferized + // before the link and what in the label link + getXWikiPrinter().setBeforeLink(true); + // escape open link syntax when before a link + if (getLinkRenderer().forceFullSyntax(getXWikiPrinter(), isFreeStandingURI, parameters) + && getXWikiPrinter().getBuffer().length() > 0 + && getXWikiPrinter().getBuffer().charAt(getXWikiPrinter().getBuffer().length() - 1) == '[') { + getXWikiPrinter().setEscapeLastChar(true); + } + getXWikiPrinter().flush(); + getXWikiPrinter().setBeforeLink(false); + + int linkDepth = getBlockState().getLinkDepth(); + + // If we are at a depth of 2 or greater it means we're in a link inside a link and in this case + // we + // shouldn't output the nested link as a link unless it's a free standing link. + if (linkDepth < 2) { + getLinkRenderer().beginRenderLink(getXWikiPrinter(), reference, isFreeStandingURI, parameters); + + XWikiSyntaxEscapeWikiPrinter linkLabelPrinter = new XWikiSyntaxEscapeWikiPrinter(new DefaultWikiPrinter(), + getXWikiSyntaxListenerChain()); + + // Make sure the escape handler knows there is already characters before + linkLabelPrinter.setOnNewLine(getXWikiPrinter().isOnNewLine()); + + // Defer printing the link content since we need to gather all nested elements + pushPrinter(linkLabelPrinter); + } else if (isFreeStandingURI) { + print(getLinkRenderer().serialize(reference, isFreeStandingURI)); + } + } + + /** + * {@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) { + // The links in a top level link label are not rendered as link (only the label is printed) + if (getBlockState().getLinkDepth() == 1) { + XWikiSyntaxEscapeWikiPrinter linkBlocksPrinter = getXWikiPrinter(); + linkBlocksPrinter.flush(); + String content = linkBlocksPrinter.toString(); + popPrinter(); + + getLinkRenderer().renderLinkContent(getXWikiPrinter(), content); + getLinkRenderer().endRenderLink(getXWikiPrinter(), reference, isFreeStandingURI, 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) { + // If the previous format had parameters and the parameters are different from the current ones + // then close them + if (this.previousFormatParameters != null) { + if (parameters.isEmpty()) { + // print("(%%)"); + // this.previousFormatParameters = null; + } else if (!this.previousFormatParameters.equals(parameters)) { + this.previousFormatParameters = null; + printParameters(parameters, false); + } else { + this.previousFormatParameters = null; + } + } else if (this.previousFormatParameters == null) { + printParameters(parameters, false); + } + + switch (format) { + case BOLD: + // Handle empty formatting parameters. + if (this.previousFormatParameters != null) { + getPrinter().print("(%%)"); + this.previousFormatParameters = null; + } + + getXWikiPrinter().printBeginBold(); + break; + case ITALIC: + // Handle empty formatting parameters. + if (this.previousFormatParameters != null) { + getPrinter().print("(%%)"); + this.previousFormatParameters = null; + } + + getXWikiPrinter().printBeginItalic(); + break; + case STRIKEDOUT: + print("--"); + break; + case UNDERLINED: + print("__"); + break; + case SUPERSCRIPT: + print("^^"); + break; + case SUBSCRIPT: + print(",,"); + break; + case MONOSPACE: + print("##"); + break; + } + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + switch (format) { + case BOLD: + print("**"); + break; + case ITALIC: + getXWikiPrinter().printEndItalic(); + break; + case STRIKEDOUT: + print("--"); + break; + case UNDERLINED: + print("__"); + break; + case SUPERSCRIPT: + print("^^"); + break; + case SUBSCRIPT: + print(",,"); + break; + case MONOSPACE: + print("##"); + break; + } + if (!parameters.isEmpty()) { + this.previousFormatParameters = parameters; + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.PrintRenderer#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + printEmptyLine(); + printParameters(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.PrintRenderer#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + this.previousFormatParameters = null; + + // Ensure that any not printed characters are flushed. + // TODO: Fix this better by introducing a state listener to handle escapes + getXWikiPrinter().flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.PrintRenderer#onNewLine() + */ + @Override + public void onNewLine() { + // - If we're inside a table cell, a paragraph, a list or a section header then if we have + // already outputted + // a new line before then this new line should be a line break in order not to break the table + // cell, + // paragraph, list or section header. + + // - If the new line is the last element of the paragraph, list or section header then it should + // be a line break + // as otherwise it'll be considered as an empty line event next time the generated syntax is + // read by the XWiki + // parser. + + if (getBlockState().isInLine()) { + if (getXWikiSyntaxListenerChain().getConsecutiveNewLineStateChainingListener().getNewLineCount() > 1) { + print("\\\\"); + } else if (getXWikiSyntaxListenerChain().getLookaheadChainingListener().getNextEvent().eventType + .isInlineEnd()) { + print("\\\\"); + } else { + print("\n"); + } + } else { + print("\n"); + } + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#onMacro(String, java.util.Map, String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + if (!isInline) { + printEmptyLine(); + print(getMacroPrinter().renderMacro(id, parameters, content, isInline)); + } else { + getXWikiPrinter().printInlineMacro(getMacroPrinter().renderMacro(id, parameters, content, isInline)); + } + } + + /** + * {@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(); + printParameters(parameters); + print(StringUtils.repeat("=", level.getAsInt()) + " "); + } + + /** + * {@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) { + print(" " + StringUtils.repeat("=", level.getAsInt())); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#onWord(String) + */ + @Override + public void onWord(String word) { + printDelayed(word); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.PrintRenderer#onSpace() + */ + @Override + public void onSpace() { + printDelayed(" "); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + printDelayed("" + symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + if (getBlockState().getListDepth() == 1) { + printEmptyLine(); + } else { + getPrinter().print("\n"); + } + + if (listType == ListType.BULLETED) { + this.listStyle.append("*"); + } else { + this.listStyle.append("1"); + } + printParameters(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.PrintRenderer#beginListItem() + */ + @Override + public void beginListItem() { + if (getBlockState().getListItemIndex() > 0) { + getPrinter().print("\n"); + } + + print(this.listStyle.toString()); + if (StringUtils.contains(this.listStyle.toString(), '1')) { + print("."); + } + print(" "); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + this.listStyle.setLength(this.listStyle.length() - 1); + + // Ensure that any not printed characters are flushed. + // TODO: Fix this better by introducing a state listener to handle escapes + getXWikiPrinter().flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + this.previousFormatParameters = null; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginMacroMarker(String, + * java.util.Map, String, + * boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) { + if (!isInline) { + printEmptyLine(); + } + + // When we encounter a macro marker we ignore all other blocks inside since we're going to use + // the macro + // definition wrapped by the macro marker to construct the xwiki syntax. + pushPrinter(new XWikiSyntaxEscapeWikiPrinter(VoidWikiPrinter.VOIDWIKIPRINTER, getXWikiSyntaxListenerChain())); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingPrintRenderer#endMacroMarker(String, java.util.Map, String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, boolean isInline) { + this.previousFormatParameters = null; + + popPrinter(); + + print(getMacroPrinter().renderMacro(name, parameters, content, isInline)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onId(String) + */ + @Override + public void onId(String name) { + print("{{id name=\"" + name + "\"/}}"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.Renderer#onHorizontalLine(Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + printEmptyLine(); + printParameters(parameters); + print("----"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.Renderer#onVerbatim(String, boolean, Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + if (!isInline) { + printEmptyLine(); + } + printParameters(parameters); + + print("{{{"); + getXWikiPrinter().printVerbatimContent(protectedString); + print("}}}"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.Renderer#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + print(StringUtils.repeat("\n", count)); + } + + /** + * {@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 { + print("\n"); + } + printParameters(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionTerm() + * @since 1.6M2 + */ + @Override + public void beginDefinitionTerm() { + if (getBlockState().getDefinitionListItemIndex() > 0) { + getPrinter().print("\n"); + } + + if (this.listStyle.length() > 0) { + print(this.listStyle.toString()); + if (this.listStyle.charAt(0) == '1') { + print("."); + } + } + print(StringUtils.repeat(":", getBlockState().getDefinitionListDepth() - 1)); + print("; "); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionDescription() + * @since 1.6M2 + */ + @Override + public void beginDefinitionDescription() { + if (getBlockState().getDefinitionListItemIndex() > 0) { + getPrinter().print("\n"); + } + + if (this.listStyle.length() > 0) { + print(this.listStyle.toString()); + if (this.listStyle.charAt(0) == '1') { + print("."); + } + } + print(StringUtils.repeat(":", getBlockState().getDefinitionListDepth() - 1)); + print(": "); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + this.previousFormatParameters = null; + + getXWikiPrinter().flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + this.previousFormatParameters = null; + + getXWikiPrinter().flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotation(java.util.Map) + * @since 1.6M2 + */ + @Override + public void beginQuotation(Map parameters) { + if (!getBlockState().isInQuotationLine()) { + printEmptyLine(); + } + + if (!parameters.isEmpty()) { + printParameters(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotationLine() + * @since 1.6M2 + */ + @Override + public void beginQuotationLine() { + if (getBlockState().getQuotationLineIndex() > 0) { + getPrinter().print("\n"); + } + + print(StringUtils.repeat(">", getBlockState().getQuotationDepth())); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + this.previousFormatParameters = null; + + getXWikiPrinter().flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + printEmptyLine(); + if (!parameters.isEmpty()) { + printParameters(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + print("|"); + printParameters(parameters, false); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + print("|="); + printParameters(parameters, false); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + if (getBlockState().getCellRow() > 0) { + print("\n"); + } + + printParameters(parameters, false); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + this.previousFormatParameters = null; + + // Ensure that any not printed characters are flushed. + // TODO: Fix this better by introducing a state listener to handle escapes + getXWikiPrinter().flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + this.previousFormatParameters = null; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onImage(org.xwiki.rendering.listener.reference.ResourceReference + * , + * boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + getImageRenderer().beginRenderLink(getXWikiPrinter(), reference, isFreeStandingURI, parameters); + getImageRenderer().endRenderLink(getXWikiPrinter(), reference, isFreeStandingURI, parameters); + } + + protected void printParameters(Map parameters) { + printParameters(parameters, true); + } + + protected void printParameters(Map parameters, boolean newLine) { + StringBuffer parametersStr = new StringBuffer(); + for (Map.Entry entry : parameters.entrySet()) { + String value = entry.getValue(); + String key = entry.getKey(); + + if (key != null && value != null) { + // Escape quotes in value to not break parameter value syntax + value = value.replaceAll("[~\"]", "~$0"); + // Escape ending custom parameters syntax + value = value.replace("%)", "~%)"); + parametersStr.append(' ').append(key).append('=').append('\"').append(value).append('\"'); + } + } + + if (parametersStr.length() > 0) { + StringBuffer buffer = new StringBuffer("(%"); + buffer.append(parametersStr); + buffer.append(" %)"); + + if (newLine) { + buffer.append("\n"); + } + + print(buffer.toString()); + } + } + + private void printDelayed(String text) { + print(text, true); + } + + private void print(String text) { + print(text, false); + } + + private void print(String text, boolean isDelayed) { + // Handle empty formatting parameters. + if (this.previousFormatParameters != null) { + getPrinter().print("(%%)"); + this.previousFormatParameters = null; + } + + if (isDelayed) { + getXWikiPrinter().printDelayed(text); + } else { + getPrinter().print(text); + } + } + + private void printEmptyLine() { + if (this.isFirstElementRendered) { + print("\n\n"); + } else { + this.isFirstElementRendered = true; + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#setPrinter(org.xwiki.rendering.renderer.printer.WikiPrinter) + * @since 2.0M3 + */ + public void setPrinter(WikiPrinter printer) { + // If the printer is already a XWiki Syntax Escape printer don't wrap it again. This case + // happens when + // the createChainingListenerInstance() method is called, ie when this renderer's state is + // stacked + // (for example when a Group event is being handled). + if (printer instanceof XWikiSyntaxEscapeWikiPrinter) { + super.setPrinter(printer); + } else { + super.setPrinter(new XWikiSyntaxEscapeWikiPrinter(printer, (XWikiSyntaxListenerChain) getListenerChain())); + } + } + + /** + * Allows exposing the additional methods of {@link XWikiSyntaxEscapeWikiPrinter}, namely the + * ability to delay + * printing some text and the ability to escape characters that would otherwise have a meaning in + * XWiki syntax. + */ + public XWikiSyntaxEscapeWikiPrinter getXWikiPrinter() { + return (XWikiSyntaxEscapeWikiPrinter) super.getPrinter(); + } + + @Override + protected void popPrinter() { + // Ensure that any not printed characters are flushed + getXWikiPrinter().flush(); + + super.popPrinter(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxEscapeHandler.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxEscapeHandler.java new file mode 100644 index 000000000..21fe651ca --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxEscapeHandler.java @@ -0,0 +1,204 @@ +/* + * 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.xwiki20; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.rendering.listener.chaining.BlockStateChainingListener; + +/** + * Escape characters that would be confused for XWiki wiki syntax if they were not escaped. + * + * @version $Id$ + * @since 2.0M3 + */ +public class XWikiSyntaxEscapeHandler { + + public static final Pattern STARLISTEND_PATTERN = Pattern.compile("(\\**([:;]*|1+\\.)?\\p{Blank})"); + + private static final Pattern LIST_PATTERN = Pattern + .compile("\\p{Blank}*((\\*+[:;]*)|([1*]+\\.[:;]*)|([:;]+))\\p{Blank}+"); + + private static final Pattern QUOTE_PATTERN = Pattern.compile("(\\>+)"); + + private static final Pattern HEADER_PATTERN = Pattern.compile("\\p{Blank}*(=+)"); + + private static final Pattern TABLE_PATTERN = Pattern.compile("\\p{Blank}*(\\||!!)"); + + private static final Pattern DOUBLE_CHARS_PATTERN = Pattern.compile("\\/\\/|\\*\\*|__|--|\\^\\^|,,|##|\\\\\\\\"); + + public static final String ESCAPE_CHAR = "~"; + + private boolean beforeLink = false; + + private boolean onNewLine = true; + + public void setOnNewLine(boolean onNewLine) { + this.onNewLine = onNewLine; + } + + public boolean isOnNewLine() { + return this.onNewLine; + } + + public void escape(StringBuffer accumulatedBuffer, XWikiSyntaxListenerChain listenerChain, boolean escapeLastChar, + Pattern escapeFirstIfMatching) { + BlockStateChainingListener blockStateListener = listenerChain.getBlockStateChainingListener(); + + // Escape tilde symbol (i.e. the escape character). + // Note: This needs to be the first replacement since other replacements below also use the + // tilde symbol + replaceAll(accumulatedBuffer, ESCAPE_CHAR, ESCAPE_CHAR + ESCAPE_CHAR); + + // Escape anything that looks like starting of custom parameters + replaceAll(accumulatedBuffer, "(%", ESCAPE_CHAR + "(%"); + + // When in a paragraph we need to escape symbols that are at beginning of lines and that could + // be confused + // with list items, headers or tables. + if (blockStateListener.isInLine() && isOnNewLine()) { + + // Look for list pattern at beginning of line and escape the first character only (it's + // enough) + escapeFirstMatchedCharacter(LIST_PATTERN, accumulatedBuffer); + + // Look for header pattern at beginning of line and escape the first character only (it's + // enough) + escapeFirstMatchedCharacter(HEADER_PATTERN, accumulatedBuffer); + + // Look for table character patterns at beginning of line and escape the first character only + // (it's enough) + escapeFirstMatchedCharacter(TABLE_PATTERN, accumulatedBuffer); + + // Look for quote pattern at beginning of line and escape the first character only (it's + // enough) + escapeFirstMatchedCharacter(QUOTE_PATTERN, accumulatedBuffer); + } + + // Escape table characters + if (blockStateListener.isInTable()) { + replaceAll(accumulatedBuffer, "|", ESCAPE_CHAR + "|"); + replaceAll(accumulatedBuffer, "!!", ESCAPE_CHAR + "!!"); + } + + if (escapeFirstIfMatching != null) { + escapeFirstMatchedCharacter(escapeFirstIfMatching, accumulatedBuffer); + } + + // When in a header we need to escape "=" symbols since otherwise they would be confused for end + // of section + // characters. + if (blockStateListener.isInHeader()) { + replaceAll(accumulatedBuffer, "=", ESCAPE_CHAR + "="); + } + + // Escape verbatim "{{{" + replaceAll(accumulatedBuffer, "{{{", ESCAPE_CHAR + "{" + ESCAPE_CHAR + "{" + ESCAPE_CHAR + "{"); + + // Escape "{{" + replaceAll(accumulatedBuffer, "{{", ESCAPE_CHAR + "{" + ESCAPE_CHAR + "{"); + + // Escape groups + replaceAll(accumulatedBuffer, "(((", ESCAPE_CHAR + "(" + ESCAPE_CHAR + "(" + ESCAPE_CHAR + "("); + replaceAll(accumulatedBuffer, ")))", ESCAPE_CHAR + ")" + ESCAPE_CHAR + ")" + ESCAPE_CHAR + ")"); + + // Escape reserved keywords + Matcher matcher = DOUBLE_CHARS_PATTERN.matcher(accumulatedBuffer.toString()); + for (int i = 0; matcher.find(); i = i + 2) { + accumulatedBuffer.replace(matcher.start() + i, matcher.end() + i, + ESCAPE_CHAR + matcher.group().charAt(0) + ESCAPE_CHAR + matcher.group().charAt(1)); + } + + // Escape ":" in "image:something", "attach:something" and "mailto:something" + // Note: even though there are some restriction in the URI specification as to what character is + // valid after + // the ":" character following the scheme we only check for characters greater than the space + // symbol for + // simplicity. + escapeURI(accumulatedBuffer, "image:"); + escapeURI(accumulatedBuffer, "attach:"); + escapeURI(accumulatedBuffer, "mailto:"); + + // Escape last character if we're told to do so. This is to handle cases such as: + // - onWord("hello:") followed by onFormat(ITALIC) which would lead to "hello://" if the ":" + // wasn't escaped + // - onWord("{") followed by onMacro() which would lead to "{{{" if the "{" wasn't escaped + if (escapeLastChar) { + accumulatedBuffer.insert(accumulatedBuffer.length() - 1, '~'); + } + + // Escape begin link + replaceAll(accumulatedBuffer, "[[", ESCAPE_CHAR + "[" + ESCAPE_CHAR + "["); + + // Escape link label + int linkLevel = getLinkLevel(listenerChain); + + if (linkLevel > 0) { + // This need to be done after anything else because link label add another level of escaping + // (escaped as + // link label and then escaped as wiki content). + String escape = StringUtils.repeat(ESCAPE_CHAR, linkLevel); + replaceAll(accumulatedBuffer, ESCAPE_CHAR, escape + ESCAPE_CHAR); + replaceAll(accumulatedBuffer, "]]", escape + "]" + escape + "]"); + replaceAll(accumulatedBuffer, ">>", escape + ">" + escape + ">"); + replaceAll(accumulatedBuffer, "||", escape + "|" + escape + "|"); + } + } + + private int getLinkLevel(XWikiSyntaxListenerChain listenerChain) { + int linkDepth = listenerChain.getBlockStateChainingListener().getLinkDepth(); + + if (this.beforeLink) { + --linkDepth; + } + + return linkDepth; + } + + public void setBeforeLink(boolean beforeLink) { + this.beforeLink = beforeLink; + } + + private void escapeURI(StringBuffer accumulatedBuffer, String match) { + int pos = accumulatedBuffer.indexOf(match); + if (pos > -1) { + // Escape the ":" symbol + accumulatedBuffer.insert(pos + match.length() - 1, '~'); + } + } + + private void replaceAll(StringBuffer accumulatedBuffer, String match, String replacement) { + int pos = -replacement.length(); + while ((pos + replacement.length() < accumulatedBuffer.length()) + && ((pos = accumulatedBuffer.indexOf(match, pos + replacement.length())) != -1)) { + accumulatedBuffer.replace(pos, pos + match.length(), replacement); + } + } + + private void escapeFirstMatchedCharacter(Pattern pattern, StringBuffer accumulatedBuffer) { + Matcher matcher = pattern.matcher(accumulatedBuffer); + if (matcher.lookingAt()) { + // Escape the first character + accumulatedBuffer.replace(matcher.start(1), matcher.start(1) + 1, ESCAPE_CHAR + matcher.group(1).charAt(0)); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxListenerChain.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxListenerChain.java new file mode 100644 index 000000000..0a01834cf --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxListenerChain.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.renderer.xwiki20; + +import org.xwiki.rendering.listener.chaining.BlockStateChainingListener; +import org.xwiki.rendering.listener.chaining.ConsecutiveNewLineStateChainingListener; +import org.xwiki.rendering.listener.chaining.GroupStateChainingListener; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.listener.chaining.LookaheadChainingListener; +import org.xwiki.rendering.listener.chaining.TextOnNewLineStateChainingListener; + +/** + * Provides convenient access to listeners in the chain used for {@link XWikiSyntaxListenerChain}. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class XWikiSyntaxListenerChain extends ListenerChain { + + /** + * @return the stateful {@link LookaheadChainingListener} for this rendering session. + */ + public LookaheadChainingListener getLookaheadChainingListener() { + return (LookaheadChainingListener) getListener(LookaheadChainingListener.class); + } + + /** + * @return the stateful {@link BlockStateChainingListener} for this rendering session. + */ + public BlockStateChainingListener getBlockStateChainingListener() { + return (BlockStateChainingListener) getListener(BlockStateChainingListener.class); + } + + /** + * @return the stateful {@link ConsecutiveNewLineStateChainingListener} for this rendering + * session. + */ + public ConsecutiveNewLineStateChainingListener getConsecutiveNewLineStateChainingListener() { + return (ConsecutiveNewLineStateChainingListener) getListener(ConsecutiveNewLineStateChainingListener.class); + } + + /** + * @return the stateful {@link TextOnNewLineStateChainingListener} for this rendering session. + */ + public TextOnNewLineStateChainingListener getTextOnNewLineStateChainingListener() { + return (TextOnNewLineStateChainingListener) getListener(TextOnNewLineStateChainingListener.class); + } + + /** + * @return the stateful {@link GroupStateChainingListener} for this rendering session. + */ + public GroupStateChainingListener getGroupStateChainingListener() { + return (GroupStateChainingListener) getListener(GroupStateChainingListener.class); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxMacroRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxMacroRenderer.java new file mode 100644 index 000000000..3377b40ba --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxMacroRenderer.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.renderer.xwiki20; + +import java.util.Map; + +import org.xwiki.rendering.internal.renderer.ParametersPrinter; + +/** + * Generates XWiki Syntax for a Macro Block. + * + * @version $Id$ + * @since 2.0.1 + */ +public class XWikiSyntaxMacroRenderer { + + private ParametersPrinter parametersPrinter = new ParametersPrinter(); + + public String renderMacro(String id, Map parameters, String content, boolean isInline) { + StringBuffer buffer = new StringBuffer(); + + // Print begin macro + buffer.append("{{"); + buffer.append(id); + + // Print parameters + if (!parameters.isEmpty()) { + buffer.append(' '); + buffer.append(renderMacroParameters(parameters)); + } + + // Print content and end macro + if (content == null) { + buffer.append("/}}"); + } else { + buffer.append("}}"); + if (content.length() > 0) { + if (!isInline) { + buffer.append("\n"); + } + buffer.append(content); + if (!isInline) { + buffer.append("\n"); + } + } + buffer.append("{{/").append(id).append("}}"); + } + + return buffer.toString(); + } + + public String renderMacroParameters(Map parameters) { + return this.parametersPrinter.print(parameters, '~').replace("}}", "~}~}"); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxRenderer.java new file mode 100644 index 000000000..1d39599c1 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxRenderer.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.xwiki20; + +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.rendering.listener.chaining.ChainingListener; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; + +/** + * Generates XWiki Syntax 2.0 from {@link org.xwiki.rendering.block.XDOM}. This is useful for + * example to convert other + * wiki syntaxes to the XWiki syntax. It's also useful in our tests to verify that round-tripping + * from XWiki Syntax to + * the DOM and back to XWiki Syntax generates the same content as the initial syntax. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("xwiki/2.0") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class XWikiSyntaxRenderer extends AbstractXWikiSyntaxRenderer { + + /** + * Needed by XWikiSyntaxChainingRenderer to serialize wiki link references. + */ + @Requirement("xwiki/2.0/link") + private ResourceReferenceSerializer linkReferenceSerializer; + + /** + * Needed by XWikiSyntaxChainingRenderer to serialize wiki image references. + */ + @Requirement("xwiki/2.0/image") + private ResourceReferenceSerializer imageReferenceSerializer; + + /** + * {@inheritDoc} + * + * @see AbstractXWikiSyntaxRenderer#createXWikiSyntaxChainingRenderer(ListenerChain) + */ + @Override + protected ChainingListener createXWikiSyntaxChainingRenderer(ListenerChain chain) { + return new XWikiSyntaxChainingRenderer(chain, this.linkReferenceSerializer, this.imageReferenceSerializer); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxRendererFactory.java new file mode 100644 index 000000000..abfc03188 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxRendererFactory.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.xwiki20; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.internal.renderer.AbstractPrintRendererFactory; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Create XWiki Syntax 2.0 Renderers. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("xwiki/2.0") +public class XWikiSyntaxRendererFactory extends AbstractPrintRendererFactory { + + /** + * {@inheritDoc} + * + * @see AbstractPrintRendererFactory#getSyntax() + */ + public Syntax getSyntax() { + return Syntax.XWIKI_2_0; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/DefaultResourceReferenceTypeSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/DefaultResourceReferenceTypeSerializer.java new file mode 100644 index 000000000..5eeab8528 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/DefaultResourceReferenceTypeSerializer.java @@ -0,0 +1,52 @@ +/* + * 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.xwiki20.reference; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.internal.parser.reference.DefaultResourceReferenceParser; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer; + +/** + * Serialize a link by outputting the link type (if the link is typed) followed by the link + * reference (ie + * "(linktype):(reference)"). + * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("xwiki/2.0") +public class DefaultResourceReferenceTypeSerializer implements ResourceReferenceTypeSerializer { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer#serialize(org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String serialize(ResourceReference reference) { + StringBuffer result = new StringBuffer(); + if (reference.isTyped()) { + result.append(reference.getType().getScheme()); + result.append(DefaultResourceReferenceParser.TYPE_SEPARATOR); + } + result.append(reference.getReference()); + return result.toString(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/DocumentReferenceTypeSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/DocumentReferenceTypeSerializer.java new file mode 100644 index 000000000..62e776444 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/DocumentReferenceTypeSerializer.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.renderer.xwiki20.reference; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.internal.parser.reference.XWiki20LinkReferenceParser; +import org.xwiki.rendering.listener.reference.DocumentResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer; + +/** + * Serialize a link reference pointing to a document using the format + * {@code (document reference)(#anchor)(?query string)}. + * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("xwiki/2.0/doc") +public class DocumentReferenceTypeSerializer implements ResourceReferenceTypeSerializer { + + /** + * Escapes to add when rendering a link reference part. + */ + private static final String[] ESCAPE_REPLACEMENTS_REFERENCE = new String[] { + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.SEPARATOR_QUERYSTRING, + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.SEPARATOR_INTERWIKI, + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.SEPARATOR_ANCHOR }; + + /** + * Replacement chars for the escapes to add to the reference part. + */ + private static final String[] ESCAPES_REFERENCE = new String[] { XWiki20LinkReferenceParser.SEPARATOR_QUERYSTRING, + XWiki20LinkReferenceParser.SEPARATOR_INTERWIKI, XWiki20LinkReferenceParser.SEPARATOR_ANCHOR }; + + /** + * Escapes to add when rendering a link query string, anchor or interwiki part. + */ + private static final String[] ESCAPE_REPLACEMENTS_EXTRA = new String[] { + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.SEPARATOR_QUERYSTRING, + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.SEPARATOR_INTERWIKI, + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.SEPARATOR_ANCHOR, + "" + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.ESCAPE_CHAR }; + + /** + * Replacement chars for the escapes to add to the query string, anchor or interwiki part. + */ + private static final String[] ESCAPES_EXTRA = new String[] { XWiki20LinkReferenceParser.SEPARATOR_QUERYSTRING, + XWiki20LinkReferenceParser.SEPARATOR_INTERWIKI, XWiki20LinkReferenceParser.SEPARATOR_ANCHOR, + "" + XWiki20LinkReferenceParser.ESCAPE_CHAR }; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer#serialize(org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String serialize(ResourceReference reference) { + StringBuilder buffer = new StringBuilder(); + + if (reference.getReference() != null) { + // Make sure we escape special chars: # and ? as they have special meaning in links, but only + // for + // links to documents. Also escape \ since it's the escape char. + String normalizedReference = addEscapesToReferencePart(reference.getReference()); + buffer.append(normalizedReference); + } + + String anchor = reference.getParameter(DocumentResourceReference.ANCHOR); + if (anchor != null) { + buffer.append('#'); + buffer.append(addEscapesToExtraParts(anchor)); + } + String queryString = reference.getParameter(DocumentResourceReference.QUERY_STRING); + if (queryString != null) { + buffer.append('?'); + buffer.append(addEscapesToExtraParts(queryString)); + } + + return buffer.toString(); + } + + /** + * @param text + * the reference to which to add escapes to + * @return the modified text + */ + protected String addEscapesToReferencePart(String text) { + return StringUtils.replaceEach(text, ESCAPES_REFERENCE, ESCAPE_REPLACEMENTS_REFERENCE); + } + + /** + * @param text + * the query string and anchor parts to which to add escapes to + * @return the modified text + */ + protected String addEscapesToExtraParts(String text) { + return StringUtils.replaceEach(text, ESCAPES_EXTRA, ESCAPE_REPLACEMENTS_EXTRA); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/InterWikiReferenceTypeSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/InterWikiReferenceTypeSerializer.java new file mode 100644 index 000000000..5a090fb08 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/InterWikiReferenceTypeSerializer.java @@ -0,0 +1,95 @@ +/* + * 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.xwiki20.reference; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.internal.parser.reference.XWiki20LinkReferenceParser; +import org.xwiki.rendering.listener.reference.InterWikiResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer; + +/** + * Serialize a link reference pointing to an interwiki link using the format + * {@code (interwiki path)@(interwiki alias)}. + * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("xwiki/2.0/interwiki") +public class InterWikiReferenceTypeSerializer implements ResourceReferenceTypeSerializer { + + /** + * Escapes to add when rendering a link reference part. + */ + private static final String[] ESCAPE_REPLACEMENTS_REFERENCE = new String[] { + "" + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.ESCAPE_CHAR }; + + /** + * Replacement chars for the escapes to add to the reference part. + */ + private static final String[] ESCAPES_REFERENCE = new String[] { "" + XWiki20LinkReferenceParser.ESCAPE_CHAR }; + + /** + * Escapes to add when rendering a link query string, anchor or interwiki part. + */ + private static final String[] ESCAPE_REPLACEMENTS_EXTRA = new String[] { + "" + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.SEPARATOR_INTERWIKI, + "" + XWiki20LinkReferenceParser.ESCAPE_CHAR + XWiki20LinkReferenceParser.ESCAPE_CHAR }; + + /** + * Replacement chars for the escapes to add to the query string, anchor or interwiki part. + */ + private static final String[] ESCAPES_EXTRA = new String[] { XWiki20LinkReferenceParser.SEPARATOR_INTERWIKI, + "" + XWiki20LinkReferenceParser.ESCAPE_CHAR }; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer#serialize(org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String serialize(ResourceReference reference) { + String interWikiAlias = reference.getParameter(InterWikiResourceReference.INTERWIKI_ALIAS); + String result = addEscapesToReferencePart(reference.getReference()); + if (interWikiAlias != null) { + result = addEscapesToReferencePart(reference.getReference()) + + XWiki20LinkReferenceParser.SEPARATOR_INTERWIKI + addEscapesToExtraParts(interWikiAlias); + } + return result; + } + + /** + * @param text + * the reference to which to add escapes to + * @return the modified text + */ + protected String addEscapesToReferencePart(String text) { + return StringUtils.replaceEach(text, ESCAPES_REFERENCE, ESCAPE_REPLACEMENTS_REFERENCE); + } + + /** + * @param text + * the query string and anchor parts to which to add escapes to + * @return the modified text + */ + protected String addEscapesToExtraParts(String text) { + return StringUtils.replaceEach(text, ESCAPES_EXTRA, ESCAPE_REPLACEMENTS_EXTRA); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxImageReferenceSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxImageReferenceSerializer.java new file mode 100644 index 000000000..6148e398a --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxImageReferenceSerializer.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.xwiki20.reference; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Generate a string representation of an Image reference, in XWiki Syntax 2.0. This implementation + * is pluggable by + * using internally implementations of + * {@link org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer}, + * each in charge of serializing a given + * {@link org.xwiki.rendering.listener.reference.ResourceType}. + *

+ * Note that {@link org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer} + * component implementations + * must use a role hint equal to the XWiki Syntax id followed by "/" and then Link Type name (eg + * "doc" for document + * links, "attach" for attachment links, etc). + *

+ * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("xwiki/2.0/image") +public class XWikiSyntaxImageReferenceSerializer extends XWikiSyntaxLinkReferenceSerializer { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer#serialize( + * org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String serialize(ResourceReference reference) { + return "image:" + super.serialize(reference); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxLinkReferenceSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxLinkReferenceSerializer.java new file mode 100644 index 000000000..33280212a --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxLinkReferenceSerializer.java @@ -0,0 +1,98 @@ +/* + * 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.xwiki20.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.renderer.reference.ResourceReferenceSerializer; +import org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer; + +/** + * Generate a string representation of a Link reference, in XWiki Syntax 2.0. This implementation is + * pluggable by using + * internally implementations of + * {@link org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer}, each in + * charge of serializing a given {@link org.xwiki.rendering.listener.reference.ResourceType}. + *

+ * Note that {@link org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer} + * component implementations + * must use a role hint equal to the XWiki Syntax id followed by "/" and then Link Type name (eg + * "doc" for document + * links, "attach" for attachment links, etc). + *

+ * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("xwiki/2.0/link") +public class XWikiSyntaxLinkReferenceSerializer implements ResourceReferenceSerializer { + + /** + * Prefix to use for + * {@link org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer} role hints. + */ + private static final String COMPONENT_PREFIX = "xwiki/2.0"; + + /** + * Used to lookup {@link org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer} + * implementations. + */ + @Requirement + private ComponentManager componentManager; + + /** + * Default serializer to use when no serializer is found for the link type. + */ + @Requirement("xwiki/2.0") + private ResourceReferenceTypeSerializer defaultResourceReferenceTypeSerializer; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer#serialize( + * org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String serialize(ResourceReference reference) { + String result; + + try { + result = this.componentManager + .lookup(ResourceReferenceTypeSerializer.class, + getLinkTypeSerializerComponentPrefix() + "/" + reference.getType().getScheme()) + .serialize(reference); + } catch (ComponentLookupException e) { + // Failed to find serializer for the passed link type. Use the default serializer. + result = this.defaultResourceReferenceTypeSerializer.serialize(reference); + } + return result; + } + + /** + * @return the role hint prefix to use when looking up + * {@link org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer} + * implementations. + */ + protected String getLinkTypeSerializerComponentPrefix() { + return COMPONENT_PREFIX; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxResourceRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxResourceRenderer.java new file mode 100644 index 000000000..2c1b642b3 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxResourceRenderer.java @@ -0,0 +1,157 @@ +/* + * 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.xwiki20.reference; + +import java.util.Map; +import java.util.Stack; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.rendering.internal.parser.PlainTextStreamParser; +import org.xwiki.rendering.internal.renderer.ParametersPrinter; +import org.xwiki.rendering.internal.renderer.printer.XWikiSyntaxEscapeWikiPrinter; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.QueueListener.Event; +import org.xwiki.rendering.listener.chaining.EventType; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; +import org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxListenerChain; + +/** + * Logic to render a Resource Reference into XWiki Syntax 2.0. + * + * @version $Id$ + * @since 2.0M3 + */ +public class XWikiSyntaxResourceRenderer { + + /** + * Separator to use between the link reference and link parameters. + */ + protected static final String PARAMETER_SEPARATOR = "||"; + + protected ParametersPrinter parametersPrinter = new ParametersPrinter(); + + private Stack forceFullSyntax = new Stack(); + + private XWikiSyntaxListenerChain listenerChain; + + private ResourceReferenceSerializer referenceSerializer; + + /** + * @since 2.5RC1 + */ + public XWikiSyntaxResourceRenderer(XWikiSyntaxListenerChain listenerChain, + ResourceReferenceSerializer referenceSerializer) { + this.listenerChain = listenerChain; + this.referenceSerializer = referenceSerializer; + this.forceFullSyntax.push(false); + } + + public String serialize(ResourceReference reference, boolean isFreeStanding) { + String result = this.referenceSerializer.serialize(reference); + + if (!isFreeStanding) { + result = result.replace("~", "~~").replace(">>", "~>~>").replace(PARAMETER_SEPARATOR, "~|~|"); + } + + return result; + } + + public void beginRenderLink(XWikiSyntaxEscapeWikiPrinter printer, ResourceReference reference, + boolean isFreeStandingURI, Map parameters) { + // find if the last printed char is part of a syntax (i.e. consumed by the parser before + // starting to parse the + // link) + boolean isLastSyntax = printer.getBuffer().length() == 0; + + printer.flush(); + + if (forceFullSyntax(printer, isLastSyntax, isFreeStandingURI, parameters)) { + this.forceFullSyntax.push(true); + + printer.print("[["); + } else { + this.forceFullSyntax.push(false); + } + } + + public boolean forceFullSyntax(XWikiSyntaxEscapeWikiPrinter printer, boolean isFreeStandingURI, + Map parameters) { + return forceFullSyntax(printer, true, isFreeStandingURI, parameters); + } + + public boolean forceFullSyntax(XWikiSyntaxEscapeWikiPrinter printer, boolean isLastSyntax, + boolean isFreeStandingURI, Map parameters) { + Event nextEvent = this.listenerChain.getLookaheadChainingListener().getNextEvent(); + + // force full syntax if + // 1: it's not a free standing URI + // 2: there is parameters + // 3: it follows a character which is not a white space (newline/space) and is not consumed by + // the parser (like + // a another link) + // 4: it's followed by a character which is not a white space (TODO: find a better way than this + // endless list of + // EventType test but it probably need some big refactoring of the printer and + // XWikiSyntaxResourceRenderer) + return !isFreeStandingURI || !parameters.isEmpty() + || (!isLastSyntax && !printer.isAfterWhiteSpace() && (!PlainTextStreamParser.SPECIALSYMBOL_PATTERN + .matcher(String.valueOf(printer.getLastPrinted().charAt(printer.getLastPrinted().length() - 1))) + .matches())) + || (nextEvent != null && nextEvent.eventType != EventType.ON_SPACE + && nextEvent.eventType != EventType.ON_NEW_LINE + && nextEvent.eventType != EventType.END_PARAGRAPH && nextEvent.eventType != EventType.END_LINK + && nextEvent.eventType != EventType.END_LIST_ITEM + && nextEvent.eventType != EventType.END_DEFINITION_DESCRIPTION + && nextEvent.eventType != EventType.END_DEFINITION_TERM + && nextEvent.eventType != EventType.END_QUOTATION_LINE + && nextEvent.eventType != EventType.END_SECTION); + } + + public void renderLinkContent(XWikiSyntaxEscapeWikiPrinter printer, String label) { + // If there was some link content specified then output the character separator ">>". + if (!StringUtils.isEmpty(label)) { + printer.print(label); + printer.print(">>"); + } + } + + public void endRenderLink(XWikiSyntaxEscapeWikiPrinter printer, ResourceReference reference, + boolean isFreeStandingURI, Map parameters) { + printer.print(serialize(reference, isFreeStandingURI)); + + // If there were parameters specified, print them + printParameters(printer, reference, parameters); + + if (this.forceFullSyntax.peek() || !isFreeStandingURI) { + printer.print("]]"); + } + + this.forceFullSyntax.pop(); + } + + protected void printParameters(XWikiSyntaxEscapeWikiPrinter printer, ResourceReference resourceReference, + Map parameters) { + // If there were parameters specified, output them separated by the "||" characters + if (!parameters.isEmpty()) { + printer.print(PARAMETER_SEPARATOR); + printer.print(this.parametersPrinter.print(parameters, '~')); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxBlockRenderer.java new file mode 100644 index 000000000..d9e61a335 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxBlockRenderer.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.renderer.xwiki21; + +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; + +/** + * Renders a {@link org.xwiki.rendering.block.Block} in XWiki Syntax 2.1. + * + * @version $Id$ + * @since 2.5M2 + */ +@Component("xwiki/2.1") +public class XWikiSyntaxBlockRenderer extends AbstractBlockRenderer { + + /** + * @see #getPrintRendererFactory() + */ + @Requirement("xwiki/2.1") + private PrintRendererFactory xwikiSyntaxRendererFactory; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.internal.renderer.AbstractBlockRenderer#getPrintRendererFactory() + */ + @Override + protected PrintRendererFactory getPrintRendererFactory() { + return this.xwikiSyntaxRendererFactory; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxChainingRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxChainingRenderer.java new file mode 100644 index 000000000..ff311ccc8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxChainingRenderer.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.renderer.xwiki21; + +import org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxListenerChain; +import org.xwiki.rendering.internal.renderer.xwiki21.reference.XWikiSyntaxResourceRenderer; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; + +/** + * Convert listener events to XWiki Syntax 2.1 output. + * + * @version $Id$ + * @since 2.5M2 + */ +public class XWikiSyntaxChainingRenderer + extends org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxChainingRenderer { + + /** + * @param listenerChain + * the rendering listener chain + * @param linkReferenceSerializer + * the serializer to use to serialize link references + * @param imageReferenceSerializer + * the serializer to use to serialize image references + * @since 2.5RC1 + */ + public XWikiSyntaxChainingRenderer(ListenerChain listenerChain, ResourceReferenceSerializer linkReferenceSerializer, + ResourceReferenceSerializer imageReferenceSerializer) { + super(listenerChain, linkReferenceSerializer, imageReferenceSerializer); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxChainingRenderer#createXWikiSyntaxLinkRenderer( + * ListenerChain, org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer) + * @since 2.5RC1 + */ + @Override + protected XWikiSyntaxResourceRenderer createXWikiSyntaxLinkRenderer(ListenerChain listenerChain, + ResourceReferenceSerializer linkReferenceSerializer) { + return new XWikiSyntaxResourceRenderer((XWikiSyntaxListenerChain) listenerChain, linkReferenceSerializer); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxChainingRenderer#createXWikiSyntaxImageRenderer( + * ListenerChain, org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer) + * @since 2.5RC1 + */ + @Override + protected XWikiSyntaxResourceRenderer createXWikiSyntaxImageRenderer(ListenerChain listenerChain, + ResourceReferenceSerializer imageReferenceSerializer) { + return new XWikiSyntaxResourceRenderer((XWikiSyntaxListenerChain) listenerChain, imageReferenceSerializer); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxRenderer.java new file mode 100644 index 000000000..17792c9c9 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxRenderer.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.internal.renderer.xwiki21; + +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.rendering.internal.renderer.xwiki20.AbstractXWikiSyntaxRenderer; +import org.xwiki.rendering.listener.chaining.ChainingListener; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; + +/** + * Generates XWiki Syntax 2.1 from {@link org.xwiki.rendering.block.XDOM}. + * + * @version $Id$ + * @since 2.5M2 + * @see org.xwiki.rendering.internal.renderer.xwiki21.XWikiSyntaxRenderer + */ +@Component("xwiki/2.1") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class XWikiSyntaxRenderer extends AbstractXWikiSyntaxRenderer { + + /** + * Needed by XWikiSyntaxChainingRenderer to serialize wiki link references. + */ + @Requirement("xwiki/2.1/link") + protected ResourceReferenceSerializer linkReferenceSerializer; + + /** + * Needed by XWikiSyntaxChainingRenderer to serialize wiki image references. + */ + @Requirement("xwiki/2.1/image") + protected ResourceReferenceSerializer imageReferenceSerializer; + + /** + * {@inheritDoc} + * + * @see AbstractXWikiSyntaxRenderer#createXWikiSyntaxChainingRenderer(ListenerChain) + */ + @Override + protected ChainingListener createXWikiSyntaxChainingRenderer(ListenerChain chain) { + return new XWikiSyntaxChainingRenderer(chain, this.linkReferenceSerializer, this.imageReferenceSerializer); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxRendererFactory.java new file mode 100644 index 000000000..684ded2fb --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxRendererFactory.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.xwiki21; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.internal.renderer.AbstractPrintRendererFactory; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Create XWiki Syntax 2.1 Renderers. + * + * @version $Id$ + * @since 2.5M2 + */ +@Component("xwiki/2.1") +public class XWikiSyntaxRendererFactory extends AbstractPrintRendererFactory { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.internal.renderer.AbstractPrintRendererFactory#getSyntax() + */ + public Syntax getSyntax() { + return Syntax.XWIKI_2_1; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/InterWikiReferenceTypeSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/InterWikiReferenceTypeSerializer.java new file mode 100644 index 000000000..151d7d308 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/InterWikiReferenceTypeSerializer.java @@ -0,0 +1,56 @@ +/* + * 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.xwiki21.reference; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.internal.parser.reference.DefaultResourceReferenceParser; +import org.xwiki.rendering.internal.parser.reference.InterWikiResourceReferenceTypeParser; +import org.xwiki.rendering.listener.reference.InterWikiResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer; + +/** + * Serialize a link reference pointing to an interwiki link using the format + * {@code (interwikialias):(interwiki path)}. + * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("xwiki/2.1/interwiki") +public class InterWikiReferenceTypeSerializer implements ResourceReferenceTypeSerializer { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer#serialize(org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String serialize(ResourceReference reference) { + StringBuffer result = new StringBuffer(); + result.append(reference.getType().getScheme()); + result.append(DefaultResourceReferenceParser.TYPE_SEPARATOR); + String interWikiAlias = reference.getParameter(InterWikiResourceReference.INTERWIKI_ALIAS); + if (interWikiAlias != null) { + result.append(interWikiAlias); + result.append(InterWikiResourceReferenceTypeParser.INTERWIKI_ALIAS_SEPARATOR); + } + result.append(reference.getReference()); + return result.toString(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxImageReferenceSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxImageReferenceSerializer.java new file mode 100644 index 000000000..d64fe03b0 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxImageReferenceSerializer.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.xwiki21.reference; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxLinkReferenceSerializer; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Generate a string representation of an Image's reference, in XWiki Syntax 2.1. + * + * @version $Id$ + * @since 2.5RC1 + */ +@Component("xwiki/2.1/image") +public class XWikiSyntaxImageReferenceSerializer extends XWikiSyntaxLinkReferenceSerializer { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer#serialize( + * org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String serialize(ResourceReference reference) { + return "image:" + super.serialize(reference); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxLinkReferenceSerializer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxLinkReferenceSerializer.java new file mode 100644 index 000000000..de46481d3 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxLinkReferenceSerializer.java @@ -0,0 +1,49 @@ +/* + * 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.xwiki21.reference; + +import org.xwiki.component.annotation.Component; + +/** + * Generate a string representation of a {@link}'s reference, in XWiki Syntax 2.1. + * + * @version $Id$ + * @since 2.3M2 + */ +@Component("xwiki/2.1/link") +public class XWikiSyntaxLinkReferenceSerializer + extends org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxLinkReferenceSerializer { + + /** + * Prefix to use for + * {@link org.xwiki.rendering.renderer.reference.ResourceReferenceTypeSerializer} role hints. + */ + private static final String COMPONENT_PREFIX = "xwiki/2.1"; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxLinkReferenceSerializer#getLinkTypeSerializerComponentPrefix() + */ + @Override + protected String getLinkTypeSerializerComponentPrefix() { + return COMPONENT_PREFIX; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxResourceRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxResourceRenderer.java new file mode 100644 index 000000000..65591c92f --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxResourceRenderer.java @@ -0,0 +1,121 @@ +/* + * 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.xwiki21.reference; + +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.rendering.internal.renderer.printer.XWikiSyntaxEscapeWikiPrinter; +import org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxListenerChain; +import org.xwiki.rendering.listener.reference.AttachmentResourceReference; +import org.xwiki.rendering.listener.reference.DocumentResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; + +/** + * Logic to render a XWiki Link into XWiki Syntax 2.1. + * + * @version $Id$ + * @since 2.5M2 + */ +public class XWikiSyntaxResourceRenderer + extends org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxResourceRenderer { + + /** + * Parameter name under which to serialize the query string in XWiki Syntax 2.1. + */ + private static final String QUERY_STRING = "queryString"; + + /** + * Parameter name under which to serialize the query string in XWiki Syntax 2.1. + */ + private static final String ANCHOR = "anchor"; + + /** + * @param listenerChain + * the rendering chain + * @param referenceSerializer + * the serializer implementation to use to serialize link references + * @since 2.5RC1 + */ + public XWikiSyntaxResourceRenderer(XWikiSyntaxListenerChain listenerChain, + ResourceReferenceSerializer referenceSerializer) { + super(listenerChain, referenceSerializer); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxResourceRenderer#printParameters( + * XWikiSyntaxEscapeWikiPrinter, org.xwiki.rendering.listener.reference.ResourceReference , + * java.util.Map) + */ + @Override + protected void printParameters(XWikiSyntaxEscapeWikiPrinter printer, ResourceReference reference, + Map parameters) { + // Print the Query String and Anchor as parameters if they're defined and if the link is a link + // to a document. + boolean shouldPrintSeparator = true; + + // The XWiki Syntax 2.1 supports two special reference parameters for document references: + // - queryString and anchor. + // The XWiki Syntax 2.1 supports one special reference parameters for attachment references: + // - queryString. + if (reference.getType().equals(ResourceType.DOCUMENT)) { + // Print first the query string + String queryString = reference.getParameter(DocumentResourceReference.QUERY_STRING); + if (!StringUtils.isEmpty(queryString)) { + printer.print(PARAMETER_SEPARATOR); + printer.print(this.parametersPrinter.print(QUERY_STRING, queryString, '~')); + shouldPrintSeparator = false; + } + // Then print the anchor + String anchor = reference.getParameter(DocumentResourceReference.ANCHOR); + if (!StringUtils.isEmpty(anchor)) { + if (shouldPrintSeparator) { + printer.print(PARAMETER_SEPARATOR); + } else { + printer.print(" "); + } + printer.print(this.parametersPrinter.print(ANCHOR, anchor, '~')); + shouldPrintSeparator = false; + } + } else if (reference.getType().equals(ResourceType.ATTACHMENT)) { + String queryString = reference.getParameter(AttachmentResourceReference.QUERY_STRING); + if (!StringUtils.isEmpty(queryString)) { + printer.print(PARAMETER_SEPARATOR); + printer.print(this.parametersPrinter.print(QUERY_STRING, queryString, '~')); + shouldPrintSeparator = false; + } + } + + // Add all Link parameters but only if there isn't a Link Reference parameter of the same + // name... + if (!parameters.isEmpty()) { + if (shouldPrintSeparator) { + printer.print(PARAMETER_SEPARATOR); + } else { + printer.print(" "); + } + printer.print(this.parametersPrinter.print(parameters, '~')); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/syntax/DefaultSyntaxFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/syntax/DefaultSyntaxFactory.java new file mode 100644 index 000000000..44fbd29b8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/syntax/DefaultSyntaxFactory.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.syntax; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.logging.AbstractLogEnabled; +import org.xwiki.rendering.parser.ParseException; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.syntax.SyntaxFactory; +import org.xwiki.rendering.syntax.SyntaxType; + +/** + * @version $Id$ + * @since 1.5M2 + */ +@Component +public class DefaultSyntaxFactory extends AbstractLogEnabled implements SyntaxFactory { + + /** + * Used to cut the syntax identifier into syntax name and syntax version. + */ + private static final Pattern SYNTAX_PATTERN = Pattern.compile("(.*)\\/(.*)"); + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.syntax.SyntaxFactory#createSyntaxFromIdString(java.lang.String) + */ + public Syntax createSyntaxFromIdString(String syntaxIdAsString) throws ParseException { + if (syntaxIdAsString == null) { + throw new ParseException("The passed Syntax cannot be NULL"); + } + + Matcher matcher = SYNTAX_PATTERN.matcher(syntaxIdAsString); + if (!matcher.matches()) { + throw new ParseException("Invalid Syntax format [" + syntaxIdAsString + "]"); + } + + String syntaxId = matcher.group(1); + String version = matcher.group(2); + + // Use the id as both the human readable name and the technical id (since the syntax string + // doesn't contain + // any information about the pretty name of a syntax type). + SyntaxType syntaxType = new SyntaxType(syntaxId, syntaxId); + + return new Syntax(syntaxType, version); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManager.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManager.java new file mode 100644 index 000000000..90f50201d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManager.java @@ -0,0 +1,83 @@ +/* + * 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.transformation; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.logging.AbstractLogEnabled; +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.configuration.RenderingConfiguration; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.transformation.Transformation; +import org.xwiki.rendering.transformation.TransformationContext; +import org.xwiki.rendering.transformation.TransformationException; +import org.xwiki.rendering.transformation.TransformationManager; + +/** + * Calls all existing transformations (executed by priority) on an existing XDOM object to generate + * a new transformed + * XDOM. + * + * @version $Id$ + * @since 1.5M2 + */ +@Component +public class DefaultTransformationManager extends AbstractLogEnabled implements TransformationManager { + + /** + * Used to get the ordered list of transformations to execute. + */ + @Requirement + private RenderingConfiguration configuration; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.transformation.TransformationManager#performTransformations(org.xwiki.rendering.block.XDOM, + * org.xwiki.rendering.syntax.Syntax) + */ + public void performTransformations(XDOM dom, Syntax syntax) throws TransformationException { + performTransformations(dom, new TransformationContext(dom, syntax)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.transformation.TransformationManager#performTransformations(org.xwiki.rendering.block.Block, + * org.xwiki.rendering.transformation.TransformationContext) + */ + public void performTransformations(Block block, TransformationContext context) throws TransformationException { + boolean error = false; + for (Transformation transformation : this.configuration.getTransformations()) { + try { + transformation.transform(block, context); + } catch (Exception e) { + // Continue running the other transformations + getLogger().error("Failed to execute transformation", e); + error = true; + } + } + if (error) { + throw new TransformationException( + "One or several transformations failed to execute properly. " + "See the logs for details."); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/CompositeListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/CompositeListener.java new file mode 100644 index 000000000..a6a159401 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/CompositeListener.java @@ -0,0 +1,620 @@ +/* + * 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.listener; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Send events to a list of {@link Listener}s. + * + * @version $Id$ + * @since 2.1M1 + */ +public class CompositeListener implements Listener { + + /** + * The listeners. + */ + private List listeners = new ArrayList(); + + /** + * Add a nex listener to the list. + * + * @param listener + * a listener + */ + public void addListener(Listener listener) { + this.listeners.add(listener); + } + + /** + * Get listener at the provided position in the list. + * + * @param i + * the index of the listener in the list + * @return the listener + */ + public Listener getListener(int i) { + return this.listeners.get(i); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionDescription() + */ + public void beginDefinitionDescription() { + for (Listener listener : listeners) { + listener.beginDefinitionDescription(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map) + */ + public void beginDefinitionList(Map parameters) { + for (Listener listener : listeners) { + listener.beginDefinitionList(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionTerm() + */ + public void beginDefinitionTerm() { + for (Listener listener : listeners) { + listener.beginDefinitionTerm(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + for (Listener listener : listeners) { + listener.beginDocument(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void beginFormat(Format format, Map parameters) { + for (Listener listener : listeners) { + listener.beginFormat(format, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginGroup(java.util.Map) + */ + public void beginGroup(Map parameters) { + for (Listener listener : listeners) { + listener.beginGroup(parameters); + } + } + + /** + * {@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) { + for (Listener listener : listeners) { + listener.beginHeader(level, id, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void beginList(ListType listType, Map parameters) { + for (Listener listener : listeners) { + listener.beginList(listType, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginListItem() + */ + public void beginListItem() { + for (Listener listener : listeners) { + listener.beginListItem(); + } + } + + /** + * {@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) { + for (Listener listener : listeners) { + listener.beginMacroMarker(name, macroParameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginParagraph(java.util.Map) + */ + public void beginParagraph(Map parameters) { + for (Listener listener : listeners) { + listener.beginParagraph(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotation(java.util.Map) + */ + public void beginQuotation(Map parameters) { + for (Listener listener : listeners) { + listener.beginQuotation(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotationLine() + */ + public void beginQuotationLine() { + for (Listener listener : listeners) { + listener.beginQuotationLine(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginSection(java.util.Map) + */ + public void beginSection(Map parameters) { + for (Listener listener : listeners) { + listener.beginSection(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map) + */ + public void beginTable(Map parameters) { + for (Listener listener : listeners) { + listener.beginTable(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map) + */ + public void beginTableCell(Map parameters) { + for (Listener listener : listeners) { + listener.beginTableCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map) + */ + public void beginTableHeadCell(Map parameters) { + for (Listener listener : listeners) { + listener.beginTableHeadCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map) + */ + public void beginTableRow(Map parameters) { + for (Listener listener : listeners) { + listener.beginTableRow(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionDescription() + */ + public void endDefinitionDescription() { + for (Listener listener : listeners) { + listener.endDefinitionDescription(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionList(java.util.Map) + */ + public void endDefinitionList(Map parameters) { + for (Listener listener : listeners) { + listener.endDefinitionList(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionTerm() + */ + public void endDefinitionTerm() { + for (Listener listener : listeners) { + listener.endDefinitionTerm(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + for (Listener listener : listeners) { + listener.endDocument(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void endFormat(Format format, Map parameters) { + for (Listener listener : listeners) { + listener.endFormat(format, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endGroup(java.util.Map) + */ + public void endGroup(Map parameters) { + for (Listener listener : listeners) { + listener.endGroup(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) { + for (Listener listener : listeners) { + listener.endHeader(level, id, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void endList(ListType listType, Map parameters) { + for (Listener listener : listeners) { + listener.endList(listType, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endListItem() + */ + public void endListItem() { + for (Listener listener : listeners) { + listener.endListItem(); + } + } + + /** + * {@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) { + for (Listener listener : listeners) { + listener.endMacroMarker(name, macroParameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endParagraph(java.util.Map) + */ + public void endParagraph(Map parameters) { + for (Listener listener : listeners) { + listener.endParagraph(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotation(java.util.Map) + */ + public void endQuotation(Map parameters) { + for (Listener listener : listeners) { + listener.endQuotation(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotationLine() + */ + public void endQuotationLine() { + for (Listener listener : listeners) { + listener.endQuotationLine(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endSection(java.util.Map) + */ + public void endSection(Map parameters) { + for (Listener listener : listeners) { + listener.endSection(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTable(java.util.Map) + */ + public void endTable(Map parameters) { + for (Listener listener : listeners) { + listener.endTable(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map) + */ + public void endTableCell(Map parameters) { + for (Listener listener : listeners) { + listener.endTableCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map) + */ + public void endTableHeadCell(Map parameters) { + for (Listener listener : listeners) { + listener.endTableHeadCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableRow(java.util.Map) + */ + public void endTableRow(Map parameters) { + for (Listener listener : listeners) { + listener.endTableRow(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + for (Listener listener : listeners) { + listener.onEmptyLines(count); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onHorizontalLine(java.util.Map) + */ + public void onHorizontalLine(Map parameters) { + for (Listener listener : listeners) { + listener.onHorizontalLine(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onId(java.lang.String) + */ + public void onId(String name) { + for (Listener listener : listeners) { + listener.onId(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) { + for (Listener listener : listeners) { + listener.onMacro(id, macroParameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onNewLine() + */ + public void onNewLine() { + for (Listener listener : listeners) { + listener.onNewLine(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onRawText(java.lang.String, + * org.xwiki.rendering.syntax.Syntax) + */ + public void onRawText(String text, Syntax syntax) { + for (Listener listener : listeners) { + listener.onRawText(text, syntax); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpace() + */ + public void onSpace() { + for (Listener listener : listeners) { + listener.onSpace(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + for (Listener listener : listeners) { + listener.onSpecialSymbol(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) { + for (Listener listener : listeners) { + listener.onVerbatim(protectedString, isInline, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onWord(java.lang.String) + */ + public void onWord(String word) { + for (Listener listener : listeners) { + listener.onWord(word); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#beginLink(org.xwiki.rendering.listener.reference.ResourceReference + * , boolean, java.util.Map) + * @since 2.5RC1 + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + for (Listener listener : listeners) { + listener.beginLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#endLink(ResourceReference , boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + for (Listener listener : listeners) { + listener.endLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.ImageListener#onImage(ResourceReference, boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + for (Listener listener : listeners) { + listener.onImage(reference, isFreeStandingURI, parameters); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Format.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Format.java new file mode 100644 index 000000000..b3ddfcfea --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Format.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.listener; + +/** + * Represents a text formatting (bold, italic, etc). + * + * @version $Id$ + * @since 1.6M1 + */ +public enum Format { + /** + * Bold style. + */ + BOLD, + + /** + * Italic style. + */ + ITALIC, + + /** + * Underlined style. + */ + UNDERLINED, + + /** + * Strikedout style. + */ + STRIKEDOUT, + + /** + * Superscript style. + */ + SUPERSCRIPT, + + /** + * Subscript style. + */ + SUBSCRIPT, + + /** + * Monospace style. + */ + MONOSPACE, + + /** + * No style. + */ + NONE +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/HeaderLevel.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/HeaderLevel.java new file mode 100644 index 000000000..96b1185d0 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/HeaderLevel.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.listener; + +/** + * @version $Id$ + * @since 1.5M2 + */ +public enum HeaderLevel { + + /** + * Header of level 1. + */ + LEVEL1, + + /** + * Header of level 2. + */ + LEVEL2, + + /** + * Header of level 3. + */ + LEVEL3, + + /** + * Header of level 4. + */ + LEVEL4, + + /** + * Header of level 5. + */ + LEVEL5, + + /** + * Header of level 6. + */ + LEVEL6; + + /** + * @return the header level as integer + */ + public int getAsInt() { + return this.ordinal() + 1; + } + + /** + * {@inheritDoc} + * + * @see java.lang.Enum#toString() + */ + @Override + public String toString() { + return "" + getAsInt(); + } + + /** + * Convert provided integer into the corresponding header level enum entry. + * + * @param value + * the header level as integer + * @return the header level as enum entry + */ + public static HeaderLevel parseInt(int value) { + HeaderLevel result; + switch (value) { + case 1: + result = HeaderLevel.LEVEL1; + break; + case 2: + result = HeaderLevel.LEVEL2; + break; + case 3: + result = HeaderLevel.LEVEL3; + break; + case 4: + result = HeaderLevel.LEVEL4; + break; + case 5: + result = HeaderLevel.LEVEL5; + break; + case 6: + result = HeaderLevel.LEVEL6; + break; + default: + throw new IllegalArgumentException("Invalid level [" + value + "]. Only levels 1 to 6 are allowed."); + } + + return result; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ImageListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ImageListener.java new file mode 100644 index 000000000..c05ba69ea --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ImageListener.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.listener; + +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Contains callback events for Images,called when a document has been parsed and when it needs to + * be modified or + * rendered. + * + * @version $Id$ + * @since 1.8RC3 + * @see Listener + */ +public interface ImageListener { + + /** + * An image. + * + * @param reference + * the image reference + * @param isFreeStandingURI + * if true then the image is defined directly as a URI in the text + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/InlineFilterListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/InlineFilterListener.java new file mode 100644 index 000000000..626774f97 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/InlineFilterListener.java @@ -0,0 +1,91 @@ +/* + * 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.listener; + +import java.util.Map; + +/** + * Wrap a listener and skip begin/endDocument events. + * + * @version $Id$ + * @since 2.7.1 + */ +public class InlineFilterListener extends WrappingListener { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + // Disable this event + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + // Disable this event + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#beginSection(java.util.Map) + */ + @Override + public void beginSection(Map parameters) { + // Filter + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + // Filter + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + // Filter + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + // Filter + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/LinkListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/LinkListener.java new file mode 100644 index 000000000..8039617af --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/LinkListener.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.listener; + +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Contains callback events for Links, called when a document has been parsed and when it needs to + * be modified or + * rendered. + * + * @version $Id$ + * @since 1.8RC3 + * @see Listener + */ +public interface LinkListener { + + /** + * Start of a link. + * + * @param reference + * the link reference + * @param isFreeStandingURI + * if true then the link is a free standing URI directly in the text + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see ResourceReference + * @since 2.5RC1 + */ + void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters); + + /** + * End of a link. + * + * @param reference + * the link reference + * @param isFreeStandingURI + * if true then the link is a free standing URI directly in the text + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see ResourceReference + * @since 2.5RC1 + */ + void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ListType.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ListType.java new file mode 100644 index 000000000..3b7409149 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ListType.java @@ -0,0 +1,36 @@ +/* + * 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.listener; + +/** + * @version $Id$ + * @since 1.5M2 + */ +public enum ListType { + /** + * Each list item start with an incremented number. + */ + NUMBERED, + + /** + * Each list item start with a bullet. + */ + BULLETED +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Listener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Listener.java new file mode 100644 index 000000000..def651bb4 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Listener.java @@ -0,0 +1,504 @@ +/* + * 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.listener; + +import java.util.Collections; +import java.util.Map; + +import org.xwiki.rendering.syntax.Syntax; + +/** + * Contains callback events called when a document has been parsed and when it needs to be modified + * or rendered. More + * specifically when a document is parsed it generates an {@link org.xwiki.rendering.block.XDOM} + * object. That object has + * a {@link org.xwiki.rendering.block.XDOM#traverse(Listener)} method that accepts a + * {@link Listener} object. For each + * {@link org.xwiki.rendering.block.Block} element found in the document its + * {@link org.xwiki.rendering.block.Block#traverse} method is called leading to the generation of + * events from this + * interface. + *

+ * Here's an example of usage: + *

+ * + *
+ * <code>
+ *   XDOM dom = parser.parse(source);
+ *   MyListener listener = new MyListener(...);
+ *   dom.traverse(listener);
+ *   // At this stage all events have been sent to MyListener.
+ * </code>
+ * 
+ * + * @version $Id$ + * @since 1.5M2 + */ +public interface Listener extends LinkListener, ImageListener { + + /** + * To use when there is no parameters. + */ + Map EMPTY_PARAMETERS = Collections.emptyMap(); + + /** + * Start of the document. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void beginDocument(Map parameters); + + /** + * End of the document. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void endDocument(Map parameters); + + /** + * Start a group of elements. Groups are used to allow using standalone elements in list items, + * table cells, etc. + * They can also be used to set parameters on a group of standalone elements. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @since 1.8.3 + */ + void beginGroup(Map parameters); + + /** + * End of the group. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @since 1.8.3 + */ + void endGroup(Map parameters); + + /** + * End of a text formatting block. + * + * @param format + * the formatting type (bold, italic, etc) + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see Format + */ + void beginFormat(Format format, Map parameters); + + /** + * End of a text formatting block. + * + * @param format + * the formatting type (bold, italic, etc) + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see Format + */ + void endFormat(Format format, Map parameters); + + /** + * Start of a paragraph. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void beginParagraph(Map parameters); + + /** + * End of a paragraph. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void endParagraph(Map parameters); + + /** + * Start of a list. + * + * @param listType + * the type of list (bulleted, numbered, etc) + * @param parameters + * a generic list of parameters for the list. Example: "style"/"background-color: blue" + * @see ListType + */ + void beginList(ListType listType, Map parameters); + + /** + * Start of a definition list. For example in HTML this is the equivalent of <dl>. + * + * @param parameters + * a generic list of parameters for the list. Example: "style"/"background-color: blue" + * @since 2.0RC1 + */ + void beginDefinitionList(Map parameters); + + /** + * End of a list. + * + * @param listType + * the type of list (bulleted, numbered, etc) + * @param parameters + * a generic list of parameters for the list. Example: "style"/"background-color: blue" + * @see ListType + */ + void endList(ListType listType, Map parameters); + + /** + * End of a definition list. For example in HTML this is the equivalent of </dl>. + * + * @param parameters + * a generic list of parameters for the list. Example: "style"/"background-color: blue" + * @since 2.0RC1 + */ + void endDefinitionList(Map parameters); + + /** + * Start of a list item. + */ + void beginListItem(); + + /** + * Start of a definition list term. For example in HTML this is the equivalent of <dt>. + * + * @since 1.6M2 + */ + void beginDefinitionTerm(); + + /** + * Start of a definition list description. For example in HTML this is the equivalent of + * <dd>. + * + * @since 1.6M2 + */ + void beginDefinitionDescription(); + + /** + * End of a list item. + */ + void endListItem(); + + /** + * End of a definition list term. For example in HTML this is the equivalent of </dt>. + * + * @since 1.6M2 + */ + void endDefinitionTerm(); + + /** + * End of a definition list description. For example in HTML this is the equivalent of + * </dd>. + * + * @since 1.6M2 + */ + void endDefinitionDescription(); + + /** + * Start of a table. + * + * @param parameters + * a generic list of parameters for the table. + * @since 1.6M2 + */ + void beginTable(Map parameters); + + /** + * Start of a table row. + * + * @param parameters + * a generic list of parameters for the table row. + * @since 1.6M2 + */ + void beginTableRow(Map parameters); + + /** + * Start of a table cell. + * + * @param parameters + * a generic list of parameters for the table cell. + * @since 1.6M2 + */ + void beginTableCell(Map parameters); + + /** + * Start of a table head cell. + * + * @param parameters + * a generic list of parameters for the table head cell. + * @since 1.6M2 + */ + void beginTableHeadCell(Map parameters); + + /** + * End of a table. + * + * @param parameters + * a generic list of parameters for the table. + * @since 1.6M2 + */ + void endTable(Map parameters); + + /** + * End of a table row. + * + * @param parameters + * a generic list of parameters for the table row. + * @since 1.6M2 + */ + void endTableRow(Map parameters); + + /** + * End of a table cell. + * + * @param parameters + * a generic list of parameters for the table cell. + * @since 1.6M2 + */ + void endTableCell(Map parameters); + + /** + * End of a table head cell. + * + * @param parameters + * a generic list of parameters for the table head cell. + * @since 1.6M2 + */ + void endTableHeadCell(Map parameters); + + /** + * Start of a section. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see org.xwiki.rendering.listener.HeaderLevel + */ + void beginSection(Map parameters); + + /** + * End of a section. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see org.xwiki.rendering.listener.HeaderLevel + */ + void endSection(Map parameters); + + /** + * Start of a header. + * + * @param level + * the header level (1, 2, 3, etc) + * @param id + * the header unique identifier + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see org.xwiki.rendering.listener.HeaderLevel + * @since 1.9M1 + */ + void beginHeader(HeaderLevel level, String id, Map parameters); + + /** + * End of a header. + * + * @param level + * the header level (1, 2, 3, etc) + * @param id + * the header unique identifier + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see org.xwiki.rendering.listener.HeaderLevel + * @since 1.9M1 + */ + void endHeader(HeaderLevel level, String id, Map parameters); + + /** + * Start of marker containing a macro definition. This is a special that Macro Blocks emits when + * they are executed + * so that it's possible to reconstruct the initial macro syntax even after Macros have been + * executed. This is used + * for exemple by the WYSIWYG editor to let use see the result of executing a macro and still let + * them modify the + * macro definition. + * + * @param name + * the macro name + * @param macroParameters + * the macro parameters + * @param content + * the macro content + * @param isInline + * if true the macro is located in a inline content (like paragraph, etc.) + * @see #onMacro(String, java.util.Map, String, boolean) + */ + void beginMacroMarker(String name, Map macroParameters, String content, boolean isInline); + + /** + * End of marker containing a macro definition. + * + * @param name + * the macro name + * @param macroParameters + * the macro parameters + * @param content + * the macro content + * @param isInline + * if true the macro is located in a inline content (like paragraph, etc.) + * @see #beginMacroMarker(String, java.util.Map, String, boolean) + */ + void endMacroMarker(String name, Map macroParameters, String content, boolean isInline); + + /** + * Start of a quotation. There are one or several quotation lines inside a quotation block. + * + * @param parameters + * a generic list of parameters for the quotation. Example: "style"/"background-color: + * blue" + */ + void beginQuotation(Map parameters); + + /** + * End of a quotation. + * + * @param parameters + * a generic list of parameters for the quotation. Example: "style"/"background-color: + * blue" + */ + void endQuotation(Map parameters); + + /** + * Start of a quotation line. There can be several quotation lines in a quotation block. + */ + void beginQuotationLine(); + + /** + * End of a quotation line. + */ + void endQuotationLine(); + + /** + * 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). + */ + void onNewLine(); + + /** + * A {@link org.xwiki.rendering.macro.Macro} by itself on a line (ie not inside another Block). + * + * @param id + * the macro id (eg "toc" for the TOC macro) + * @param macroParameters + * the macro parameters + * @param content + * the macro content + * @param isInline + * if true the macro is located in a inline content (like paragraph, etc.) + * @since 1.6M2 + */ + void onMacro(String id, Map macroParameters, String content, boolean isInline); + + /** + * A word. Note that sentences ar broken into different events: word events, special symbols + * events, space events, + * etc. This allows fine-grained actions for listeners. + * + * @param word + * the word encountered + */ + void onWord(String word); + + /** + * A space. + */ + void onSpace(); + + /** + * A special symbol ("*", "<", ">", "=", quote, etc). Any non alpha numeric character is a special + * symbol. + * + * @param symbol + * the symbol encountered + */ + void onSpecialSymbol(char symbol); + + /** + * 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. Note that there is no wiki syntax for this in general and it's + * often generated by + * Macros (such as the TOC Macro). + * + * @param name + * the location name. + * @since 1.6M1 + */ + void onId(String name); + + /** + * Represents an horizontal line. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @since 1.6M1 + */ + void onHorizontalLine(Map parameters); + + /** + * 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. + * + * @param count + * the number of empty lines between 2 standalone Blocks + */ + void onEmptyLines(int count); + + /** + * A portion of text. + * + * @param protectedString + * the string to protected from rendering + * @param isInline + * if true the text content is located in a inline content (like paragraph, etc.) + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void onVerbatim(String protectedString, boolean isInline, Map parameters); + + /** + * Some text to inject directly into the listener output without parsing it. For example a HTML + * macro could inject + * directly some HTML entered by the user into the rendered HTML output. Note that it's not + * recommended to use this + * event in most cases since it can lead to invalid content being generated and in addition most + * listener + * implementations will not understand the injected text and will just ignore it. + * + * @param rawContent + * the text to inject + * @param syntax + * the syntax in which the text is written. This is useful so that listener + * implementations can decide + * whether they can handle direct inject for that syntax + */ + void onRawText(String rawContent, Syntax syntax); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/QueueListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/QueueListener.java new file mode 100644 index 000000000..362371f07 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/QueueListener.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.listener; + +import java.util.LinkedList; +import java.util.Map; + +import org.xwiki.rendering.listener.chaining.EventType; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Manage a {@link java.util.Queue} of events. + * + * @version $Id$ + * @since 2.1M1 + */ +public class QueueListener extends LinkedList implements Listener { + + /** + * Class ID for serialization. + */ + private static final long serialVersionUID = 2869508092440006345L; + + /** + * An event. + * + * @version $Id$ + */ + public class Event { + + /** + * The type of the event. + */ + public EventType eventType; + + /** + * The parameters of the event. + */ + public Object[] eventParameters; + + /** + * @param eventType + * the type of the event + * @param eventParameters + * the parameters of the event + */ + public Event(EventType eventType, Object[] eventParameters) { + this.eventType = eventType; + this.eventParameters = eventParameters; + } + } + + /** + * Returns the event at the specified position in this queue. + * + * @param depth + * index of event to return. + * @return the evnet at the specified position in this queue. + */ + public Event getEvent(int depth) { + Event event = null; + + if (depth > 0 && size() > depth - 1) { + event = get(depth - 1); + } + + return event; + } + + /** + * Send all stored events to provided {@link Listener}. + * + * @param listener + * the {@link Listener} on which to send events + */ + public void consumeEvents(Listener listener) { + while (!isEmpty()) { + Event event = remove(); + event.eventType.fireEvent(listener, event.eventParameters); + } + } + + /** + * Store provided event. + * + * @param eventType + * the type of the event + * @param objects + * the parameters of the event + */ + private void saveEvent(EventType eventType, Object... objects) { + offer(new Event(eventType, objects)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionDescription() + */ + public void beginDefinitionDescription() { + saveEvent(EventType.BEGIN_DEFINITION_DESCRIPTION); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void beginDefinitionList(Map parameters) { + saveEvent(EventType.BEGIN_DEFINITION_LIST, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionTerm() + */ + public void beginDefinitionTerm() { + saveEvent(EventType.BEGIN_DEFINITION_TERM); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + saveEvent(EventType.BEGIN_DOCUMENT, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginGroup(Map) + */ + public void beginGroup(Map parameters) { + saveEvent(EventType.BEGIN_GROUP, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void beginFormat(Format format, Map parameters) { + saveEvent(EventType.BEGIN_FORMAT, format, parameters); + } + + /** + * {@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) { + saveEvent(EventType.BEGIN_HEADER, level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginLink(ResourceReference , boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + saveEvent(EventType.BEGIN_LINK, reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void beginList(ListType listType, Map parameters) { + saveEvent(EventType.BEGIN_LIST, listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginListItem() + */ + public void beginListItem() { + saveEvent(EventType.BEGIN_LIST_ITEM); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) { + saveEvent(EventType.BEGIN_MACRO_MARKER, name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginParagraph(java.util.Map) + */ + public void beginParagraph(Map parameters) { + saveEvent(EventType.BEGIN_PARAGRAPH, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotation(java.util.Map) + */ + public void beginQuotation(Map parameters) { + saveEvent(EventType.BEGIN_QUOTATION, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotationLine() + */ + public void beginQuotationLine() { + saveEvent(EventType.BEGIN_QUOTATION_LINE); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginSection(java.util.Map) + */ + public void beginSection(Map parameters) { + saveEvent(EventType.BEGIN_SECTION, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map) + */ + public void beginTable(Map parameters) { + saveEvent(EventType.BEGIN_TABLE, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map) + */ + public void beginTableCell(Map parameters) { + saveEvent(EventType.BEGIN_TABLE_CELL, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map) + */ + public void beginTableHeadCell(Map parameters) { + saveEvent(EventType.BEGIN_TABLE_HEAD_CELL, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map) + */ + public void beginTableRow(Map parameters) { + saveEvent(EventType.BEGIN_TABLE_ROW, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionDescription() + */ + public void endDefinitionDescription() { + saveEvent(EventType.END_DEFINITION_DESCRIPTION); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void endDefinitionList(Map parameters) { + saveEvent(EventType.END_DEFINITION_LIST, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionTerm() + */ + public void endDefinitionTerm() { + saveEvent(EventType.END_DEFINITION_TERM); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + saveEvent(EventType.END_DOCUMENT, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endGroup(Map) + */ + public void endGroup(Map parameters) { + saveEvent(EventType.END_GROUP, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void endFormat(Format format, Map parameters) { + saveEvent(EventType.END_FORMAT, format, 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) { + saveEvent(EventType.END_HEADER, level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endLink(ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + saveEvent(EventType.END_LINK, reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void endList(ListType listType, Map parameters) { + saveEvent(EventType.END_LIST, listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endListItem() + */ + public void endListItem() { + saveEvent(EventType.END_LIST_ITEM); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void endMacroMarker(String name, Map parameters, String content, boolean isInline) { + saveEvent(EventType.END_MACRO_MARKER, name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endParagraph(java.util.Map) + */ + public void endParagraph(Map parameters) { + saveEvent(EventType.END_PARAGRAPH, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotation(java.util.Map) + */ + public void endQuotation(Map parameters) { + saveEvent(EventType.END_QUOTATION, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotationLine() + */ + public void endQuotationLine() { + saveEvent(EventType.END_QUOTATION_LINE); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endSection(java.util.Map) + */ + public void endSection(Map parameters) { + saveEvent(EventType.END_SECTION, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTable(java.util.Map) + */ + public void endTable(Map parameters) { + saveEvent(EventType.END_TABLE, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map) + */ + public void endTableCell(Map parameters) { + saveEvent(EventType.END_TABLE_CELL, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map) + */ + public void endTableHeadCell(Map parameters) { + saveEvent(EventType.END_TABLE_HEAD_CELL, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableRow(java.util.Map) + */ + public void endTableRow(Map parameters) { + saveEvent(EventType.END_TABLE_ROW, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onRawText(String, Syntax) + */ + public void onRawText(String text, Syntax syntax) { + saveEvent(EventType.ON_RAW_TEXT, text, syntax); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + saveEvent(EventType.ON_EMPTY_LINES, count); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onHorizontalLine(java.util.Map) + */ + public void onHorizontalLine(Map parameters) { + saveEvent(EventType.ON_HORIZONTAL_LINE, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onId(java.lang.String) + */ + public void onId(String name) { + saveEvent(EventType.ON_ID, name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onImage(ResourceReference, boolean, java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + saveEvent(EventType.ON_IMAGE, reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onMacro(java.lang.String, java.util.Map, + * java.lang.String, boolean) + */ + public void onMacro(String id, Map parameters, String content, boolean isInline) { + saveEvent(EventType.ON_MACRO, id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onNewLine() + */ + public void onNewLine() { + saveEvent(EventType.ON_NEW_LINE); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpace() + */ + public void onSpace() { + saveEvent(EventType.ON_SPACE); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + saveEvent(EventType.ON_SPECIAL_SYMBOL, symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onVerbatim(String, boolean, Map) + */ + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + saveEvent(EventType.ON_VERBATIM, protectedString, isInline, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onWord(java.lang.String) + */ + public void onWord(String word) { + saveEvent(EventType.ON_WORD, word); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/WrappingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/WrappingListener.java new file mode 100644 index 000000000..4bdcd5204 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/WrappingListener.java @@ -0,0 +1,519 @@ +/* + * 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.listener; + +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.syntax.Syntax; + +/** + * A Listener wrapping another Listener. + * + * @version $Id$ + */ +public class WrappingListener implements Listener { + + /** + * The Listener to wrap. + */ + private Listener listener; + + /** + * @param listener + * the Listener to wrap + */ + public void setWrappedListener(Listener listener) { + this.listener = listener; + } + + /** + * @return the Listener to wrap + */ + public Listener getWrappedListener() { + return this.listener; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + this.listener.beginDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + this.listener.endDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginGroup(Map) + */ + public void beginGroup(Map parameters) { + this.listener.beginGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endGroup(Map) + */ + public void endGroup(Map parameters) { + this.listener.endGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginFormat(Format, Map) + */ + public void beginFormat(Format format, Map parameters) { + this.listener.beginFormat(format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void beginList(ListType listType, Map parameters) { + this.listener.beginList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginListItem() + */ + public void beginListItem() { + this.listener.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) { + this.listener.beginMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginParagraph(java.util.Map) + */ + public void beginParagraph(Map parameters) { + this.listener.beginParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginSection(java.util.Map) + */ + public void beginSection(Map parameters) { + this.listener.beginSection(parameters); + } + + /** + * {@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.listener.beginHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endFormat(Format, Map) + */ + public void endFormat(Format format, Map parameters) { + this.listener.endFormat(format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void endList(ListType listType, Map parameters) { + this.listener.endList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endListItem() + */ + public void endListItem() { + this.listener.endListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void endMacroMarker(String name, Map parameters, String content, boolean isInline) { + this.listener.endMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endParagraph(java.util.Map) + */ + public void endParagraph(Map parameters) { + this.listener.endParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endSection(java.util.Map) + */ + public void endSection(Map parameters) { + this.listener.endSection(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.listener.endHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#beginLink(ResourceReference , boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.listener.beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#endLink(ResourceReference , boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.listener.endLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onMacro(java.lang.String, java.util.Map, + * java.lang.String, boolean) + */ + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.listener.onMacro(id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onNewLine() + */ + public void onNewLine() { + this.listener.onNewLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpace() + */ + public void onSpace() { + this.listener.onSpace(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + this.listener.onSpecialSymbol(symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onWord(java.lang.String) + */ + public void onWord(String word) { + this.listener.onWord(word); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onId(java.lang.String) + */ + public void onId(String name) { + this.listener.onId(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onHorizontalLine(Map) + */ + public void onHorizontalLine(Map parameters) { + this.listener.onHorizontalLine(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + this.listener.onEmptyLines(count); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onVerbatim(String, boolean, Map) + */ + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.listener.onVerbatim(protectedString, isInline, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onRawText(String, Syntax) + */ + public void onRawText(String text, Syntax syntax) { + this.listener.onRawText(text, syntax); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void beginDefinitionList(Map parameters) { + this.listener.beginDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void endDefinitionList(Map parameters) { + this.listener.endDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see Listener#beginDefinitionTerm() + * @since 1.6M2 + */ + public void beginDefinitionTerm() { + this.listener.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see Listener#beginDefinitionDescription() + * @since 1.6M2 + */ + public void beginDefinitionDescription() { + this.listener.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see Listener#endDefinitionTerm() + * @since 1.6M2 + */ + public void endDefinitionTerm() { + this.listener.endDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see Listener#endDefinitionDescription() + * @since 1.6M2 + */ + public void endDefinitionDescription() { + this.listener.endDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see Listener#beginQuotation(java.util.Map) + * @since 1.6M2 + */ + public void beginQuotation(Map parameters) { + this.listener.beginQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see Listener#endQuotation(java.util.Map) + * @since 1.6M2 + */ + public void endQuotation(Map parameters) { + this.listener.endQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotationLine() + * @since 1.6M2 + */ + public void beginQuotationLine() { + this.listener.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotationLine() + * @since 1.6M2 + */ + public void endQuotationLine() { + this.listener.endQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map) + */ + public void beginTable(Map parameters) { + this.listener.beginTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map) + */ + public void beginTableCell(Map parameters) { + this.listener.beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map) + */ + public void beginTableHeadCell(Map parameters) { + this.listener.beginTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map) + */ + public void beginTableRow(Map parameters) { + this.listener.beginTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTable(java.util.Map) + */ + public void endTable(Map parameters) { + this.listener.endTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map) + */ + public void endTableCell(Map parameters) { + this.listener.endTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map) + */ + public void endTableHeadCell(Map parameters) { + this.listener.endTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableRow(java.util.Map) + */ + public void endTableRow(Map parameters) { + this.listener.endTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onImage(ResourceReference, boolean, java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.listener.onImage(reference, isFreeStandingURI, parameters); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/AbstractChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/AbstractChainingListener.java new file mode 100644 index 000000000..3be2151c4 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/AbstractChainingListener.java @@ -0,0 +1,656 @@ +/* + * 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.listener.chaining; + +import java.util.Map; + +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.syntax.Syntax; + +/** + * Default and basic implementation of a chaining listener that knows how to delegate event calls to + * the next listener + * in the chain. + * + * @version $Id$ + * @since 1.8RC1 + */ +public abstract class AbstractChainingListener implements ChainingListener { + + /** + * The chain to use to know the next listener to call on events. + */ + private ListenerChain listenerChain; + + /** + * @param listenerChain + * see {@link #getListenerChain()} + * @since 2.0M3 + */ + public void setListenerChain(ListenerChain listenerChain) { + this.listenerChain = listenerChain; + } + + /** + * @return the listener chain used to know the next listener to call on events + */ + public ListenerChain getListenerChain() { + return this.listenerChain; + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginDefinitionDescription() + */ + public void beginDefinitionDescription() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginDefinitionDescription(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void beginDefinitionList(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginDefinitionList(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginDefinitionTerm() + */ + public void beginDefinitionTerm() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginDefinitionTerm(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginDocument(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginGroup(Map) + */ + public void beginGroup(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginGroup(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginFormat(Format, Map) + */ + public void beginFormat(Format format, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginFormat(format, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginHeader(HeaderLevel, String, Map) + */ + public void beginHeader(HeaderLevel level, String id, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginHeader(level, id, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginLink(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, Map) + * @since 2.5RC1 + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginList(ListType, Map) + */ + public void beginList(ListType listType, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginList(listType, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginListItem() + */ + public void beginListItem() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginListItem(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginMacroMarker(String, Map, String, boolean) + */ + public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginMacroMarker(name, parameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginParagraph(Map) + */ + public void beginParagraph(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginParagraph(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginQuotation(Map) + */ + public void beginQuotation(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginQuotation(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginQuotationLine() + */ + public void beginQuotationLine() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginQuotationLine(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginSection(Map) + */ + public void beginSection(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginSection(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginTable(Map) + */ + public void beginTable(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginTable(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginTableCell(Map) + */ + public void beginTableCell(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginTableCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginTableHeadCell(Map) + */ + public void beginTableHeadCell(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginTableHeadCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginTableRow(Map) + */ + public void beginTableRow(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginTableRow(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endDefinitionDescription() + */ + public void endDefinitionDescription() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endDefinitionDescription(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void endDefinitionList(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endDefinitionList(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endDefinitionTerm() + */ + public void endDefinitionTerm() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endDefinitionTerm(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endDocument(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endGroup(Map) + */ + public void endGroup(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endGroup(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endFormat(Format, Map) + */ + public void endFormat(Format format, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endFormat(format, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endHeader(HeaderLevel, String, Map) + */ + public void endHeader(HeaderLevel level, String id, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endHeader(level, id, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endLink(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, Map) + * @since 2.5RC1 + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endList(ListType, Map) + */ + public void endList(ListType listType, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endList(listType, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endListItem() + */ + public void endListItem() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endListItem(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endMacroMarker(String, Map, String, boolean) + */ + public void endMacroMarker(String name, Map parameters, String content, boolean isInline) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endMacroMarker(name, parameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endParagraph(Map) + */ + public void endParagraph(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endParagraph(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endQuotation(Map) + */ + public void endQuotation(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endQuotation(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endQuotationLine() + */ + public void endQuotationLine() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endQuotationLine(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endSection(Map) + */ + public void endSection(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endSection(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endTable(Map) + */ + public void endTable(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endTable(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endTableCell(Map) + */ + public void endTableCell(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endTableCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endTableHeadCell(Map) + */ + public void endTableHeadCell(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endTableHeadCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endTableRow(Map) + */ + public void endTableRow(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endTableRow(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onEmptyLines(count); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onHorizontalLine(Map) + */ + public void onHorizontalLine(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onHorizontalLine(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onId(String) + */ + public void onId(String name) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onId(name); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onImage(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onImage(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onMacro(String, Map, String, boolean) + */ + public void onMacro(String id, Map parameters, String content, boolean isInline) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onMacro(id, parameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onNewLine() + */ + public void onNewLine() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onNewLine(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onSpace() + */ + public void onSpace() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onSpace(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onSpecialSymbol(symbol); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onVerbatim(String, boolean, Map) + */ + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onVerbatim(protectedString, isInline, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onWord(String) + */ + public void onWord(String word) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onWord(word); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onRawText(String, Syntax) + */ + public void onRawText(String text, Syntax syntax) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onRawText(text, syntax); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/BlockStateChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/BlockStateChainingListener.java new file mode 100644 index 000000000..ec0c6c84c --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/BlockStateChainingListener.java @@ -0,0 +1,784 @@ +/* + * 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.listener.chaining; + +import java.util.Map; +import java.util.Stack; + +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.syntax.Syntax; + +/** + * Indicates block element for which we are inside and previous blocks. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class BlockStateChainingListener extends AbstractChainingListener implements StackableChainingListener { + + public enum Event { + NONE, DEFINITION_DESCRIPTION, DEFINITION_TERM, DEFINITION_LIST, DOCUMENT, FORMAT, HEADER, LINK, LIST, LIST_ITEM, MACRO_MARKER, PARAGRAPH, QUOTATION, QUOTATION_LINE, SECTION, TABLE, TABLE_CELL, TABLE_HEAD_CELL, TABLE_ROW, RAW_TEXT, EMPTY_LINES, HORIZONTAL_LINE, ID, IMAGE, NEW_LINE, SPACE, SPECIAL_SYMBOL, MACRO, VERBATIM_INLINE, VERBATIM_STANDALONE, WORD + } + + private Event previousEvent = Event.NONE; + + private int inlineDepth; + + private boolean isInParagraph; + + private boolean isInHeader; + + private int linkDepth; + + private boolean isInTable; + + private boolean isInTableCell; + + private Stack definitionListDepth = new Stack(); + + private Stack listDepth = new Stack(); + + private int quotationDepth; + + private int quotationLineDepth; + + private int quotationLineIndex = -1; + + private int macroDepth; + + private int cellRow = -1; + + private int cellCol = -1; + + public BlockStateChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + /** + * {@inheritDoc} + * + * @see StackableChainingListener#createChainingListenerInstance() + */ + public StackableChainingListener createChainingListenerInstance() { + return new BlockStateChainingListener(getListenerChain()); + } + + public Event getPreviousEvent() { + return this.previousEvent; + } + + public int getInlineDepth() { + return this.inlineDepth; + } + + public boolean isInLine() { + return getInlineDepth() > 0; + } + + public boolean isInParagraph() { + return this.isInParagraph; + } + + public boolean isInHeader() { + return this.isInHeader; + } + + public boolean isInTable() { + return this.isInTable; + } + + public boolean isInTableCell() { + return this.isInTableCell; + } + + public int getCellCol() { + return this.cellCol; + } + + public int getCellRow() { + return this.cellRow; + } + + public int getDefinitionListDepth() { + return this.definitionListDepth.size(); + } + + public boolean isInDefinitionList() { + return getDefinitionListDepth() > 0; + } + + public int getDefinitionListItemIndex() { + return isInDefinitionList() ? this.definitionListDepth.peek().definitionListItemIndex : -1; + } + + public int getListDepth() { + return this.listDepth.size(); + } + + public boolean isInList() { + return getListDepth() > 0; + } + + public int getListItemIndex() { + return isInList() ? this.listDepth.peek().listItemIndex : -1; + } + + public void pushLinkDepth() { + ++this.linkDepth; + } + + public void popLinkDepth() { + --this.linkDepth; + } + + public int getLinkDepth() { + return this.linkDepth; + } + + public boolean isInLink() { + return getLinkDepth() > 0; + } + + public int getQuotationDepth() { + return this.quotationDepth; + } + + public boolean isInQuotation() { + return getQuotationDepth() > 0; + } + + public int getQuotationLineDepth() { + return this.quotationLineDepth; + } + + public boolean isInQuotationLine() { + return getQuotationLineDepth() > 0; + } + + public int getQuotationLineIndex() { + return this.quotationLineIndex; + } + + public int getMacroDepth() { + return this.macroDepth; + } + + public boolean isInMacro() { + return getMacroDepth() > 0; + } + + // Events + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + ++this.inlineDepth; + ++this.definitionListDepth.peek().definitionListItemIndex; + + super.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + this.definitionListDepth.push(new DefinitionListState()); + + super.beginDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + ++this.inlineDepth; + ++this.definitionListDepth.peek().definitionListItemIndex; + + super.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + ++this.linkDepth; + + super.beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + this.listDepth.push(new ListState()); + + super.beginList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginListItem() + */ + @Override + public void beginListItem() { + ++this.inlineDepth; + ++this.listDepth.peek().listItemIndex; + + super.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) { + ++this.macroDepth; + + super.beginMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + this.isInParagraph = true; + ++this.inlineDepth; + + super.beginParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + ++this.quotationDepth; + + super.beginQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + ++this.quotationLineDepth; + ++this.inlineDepth; + ++this.quotationLineIndex; + + super.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + this.isInHeader = true; + ++this.inlineDepth; + + super.beginHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + this.isInTable = true; + + super.beginTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + ++this.cellRow; + + super.beginTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + this.isInTableCell = true; + ++this.inlineDepth; + ++this.cellCol; + + super.beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + this.isInTableCell = true; + ++this.inlineDepth; + ++this.cellCol; + + super.beginTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + super.endDefinitionDescription(); + + --this.inlineDepth; + this.previousEvent = Event.DEFINITION_DESCRIPTION; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + super.endDefinitionList(parameters); + + this.definitionListDepth.pop(); + + this.previousEvent = Event.DEFINITION_LIST; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + super.endDefinitionTerm(); + + --this.inlineDepth; + this.previousEvent = Event.DEFINITION_TERM; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + this.previousEvent = Event.DOCUMENT; + + super.endDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + super.endFormat(format, parameters); + + this.previousEvent = Event.FORMAT; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + super.endLink(reference, isFreeStandingURI, parameters); + + --this.linkDepth; + this.previousEvent = Event.LINK; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + super.endList(listType, parameters); + + this.listDepth.pop(); + + this.previousEvent = Event.LIST; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + super.endListItem(); + + --this.inlineDepth; + this.previousEvent = Event.LIST_ITEM; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, boolean isInline) { + super.endMacroMarker(name, parameters, content, isInline); + + this.previousEvent = Event.MACRO_MARKER; + --this.macroDepth; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + super.endParagraph(parameters); + + this.isInParagraph = false; + --this.inlineDepth; + this.previousEvent = Event.PARAGRAPH; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + super.endQuotation(parameters); + + --this.quotationDepth; + if (this.quotationDepth == 0) { + this.quotationLineIndex = -1; + } + this.previousEvent = Event.QUOTATION; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + super.endQuotationLine(); + + --this.quotationLineDepth; + --this.inlineDepth; + this.previousEvent = Event.QUOTATION_LINE; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + super.endSection(parameters); + + this.previousEvent = Event.SECTION; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + super.endHeader(level, id, parameters); + + this.isInHeader = false; + --this.inlineDepth; + this.previousEvent = Event.HEADER; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + super.endTable(parameters); + + this.isInTable = false; + this.cellRow = -1; + this.previousEvent = Event.TABLE; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + super.endTableCell(parameters); + + this.isInTableCell = false; + --this.inlineDepth; + this.previousEvent = Event.TABLE_CELL; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + super.endTableHeadCell(parameters); + + this.isInTableCell = false; + --this.inlineDepth; + this.previousEvent = Event.TABLE_HEAD_CELL; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + super.endTableRow(parameters); + + this.previousEvent = Event.TABLE_ROW; + this.cellCol = -1; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + super.onRawText(text, syntax); + + this.previousEvent = Event.RAW_TEXT; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + this.previousEvent = Event.EMPTY_LINES; + + super.onEmptyLines(count); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + this.previousEvent = Event.HORIZONTAL_LINE; + + super.onHorizontalLine(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + this.previousEvent = Event.ID; + + super.onId(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.previousEvent = Event.IMAGE; + + super.onImage(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + this.previousEvent = Event.NEW_LINE; + + super.onNewLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpace() + */ + @Override + public void onSpace() { + this.previousEvent = Event.SPACE; + + super.onSpace(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + this.previousEvent = Event.SPECIAL_SYMBOL; + + super.onSpecialSymbol(symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.previousEvent = Event.VERBATIM_STANDALONE; + + super.onVerbatim(protectedString, isInline, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + this.previousEvent = Event.WORD; + + super.onWord(word); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.previousEvent = Event.MACRO; + + super.onMacro(id, parameters, content, isInline); + } + + private static class ListState { + + public int listItemIndex = -1; + } + + private static class DefinitionListState { + + public int definitionListItemIndex = -1; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ChainingListener.java new file mode 100644 index 000000000..e1081c6d6 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ChainingListener.java @@ -0,0 +1,38 @@ +/* + * 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.listener.chaining; + +import org.xwiki.rendering.listener.Listener; + +/** + * A listener that can be chained with other chaining listeners using a chain. This allows creating + * listeners to filter + * some events, to aggregate state information in a decoupled manner, to perform lookaheads, etc. + * + * @version $Id$ + * @since 1.8RC1 + */ +public interface ChainingListener extends Listener { + + /** + * @return the chain this listener is part of + */ + ListenerChain getListenerChain(); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ConsecutiveNewLineStateChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ConsecutiveNewLineStateChainingListener.java new file mode 100644 index 000000000..9a671ff88 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ConsecutiveNewLineStateChainingListener.java @@ -0,0 +1,397 @@ +/* + * 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.listener.chaining; + +import java.util.Map; + +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.syntax.Syntax; + +/** + * Counts consecutive new lines. + * + * @version $Id; $ + * @since 1.8RC1 + */ +public class ConsecutiveNewLineStateChainingListener extends AbstractChainingListener + implements StackableChainingListener { + + /** + * Number of found new lines. + */ + private int newLineCount; + + /** + * @param listenerChain + * see {@link #getListenerChain()} + */ + public ConsecutiveNewLineStateChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + /** + * {@inheritDoc} + * + * @see StackableChainingListener#createChainingListenerInstance() + */ + public StackableChainingListener createChainingListenerInstance() { + return new ConsecutiveNewLineStateChainingListener(getListenerChain()); + } + + /** + * @return the number of found new lines. + */ + public int getNewLineCount() { + return this.newLineCount; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + this.newLineCount = 0; + super.endDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + this.newLineCount = 0; + super.endDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + this.newLineCount = 0; + super.endDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + this.newLineCount = 0; + super.endDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map) + */ + @Override + public void endGroup(Map parameters) { + this.newLineCount = 0; + super.endGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + this.newLineCount = 0; + super.endFormat(format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.newLineCount = 0; + super.endLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + this.newLineCount = 0; + super.endList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + this.newLineCount = 0; + super.endListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, boolean isInline) { + this.newLineCount = 0; + super.endMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + this.newLineCount = 0; + super.endParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + this.newLineCount = 0; + super.endQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + this.newLineCount = 0; + super.endQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + this.newLineCount = 0; + super.endHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + this.newLineCount = 0; + super.endTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + this.newLineCount = 0; + super.endTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + this.newLineCount = 0; + super.endTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + this.newLineCount = 0; + super.endTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + this.newLineCount = 0; + super.onRawText(text, syntax); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + this.newLineCount = 0; + super.onEmptyLines(count); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + this.newLineCount = 0; + super.onHorizontalLine(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + this.newLineCount = 0; + super.onId(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.newLineCount = 0; + super.onImage(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + this.newLineCount++; + super.onNewLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpace() + */ + @Override + public void onSpace() { + this.newLineCount = 0; + super.onSpace(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + this.newLineCount = 0; + super.onSpecialSymbol(symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(String, Map, + * String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.newLineCount = 0; + super.onMacro(id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.newLineCount = 0; + super.onVerbatim(protectedString, isInline, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + this.newLineCount = 0; + super.onWord(word); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListener.java new file mode 100644 index 000000000..4b7428121 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListener.java @@ -0,0 +1,641 @@ +/* + * 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.listener.chaining; + +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.HeaderLevel; + +import java.util.Map; +import java.util.Stack; + +/** + * Allow knowing if a container block (a block which can have children) has children or not. + * + * @version $Id$ + * @since 2.0M3 + */ +public class EmptyBlockChainingListener extends AbstractChainingListener { + + private Stack containerBlockStates = new Stack(); + + public EmptyBlockChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + public boolean isCurrentContainerBlockEmpty() { + return this.containerBlockStates.peek(); + } + + // Events + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + startContainerBlock(); + super.beginDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + markNotEmpty(); + startContainerBlock(); + super.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + markNotEmpty(); + startContainerBlock(); + super.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(java.util.Map) + */ + @Override + public void beginGroup(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingListener#beginFormat(org.xwiki.rendering.listener.Format, java.util.Map) + */ + @Override + public void beginFormat(Format format, Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginFormat(format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginListItem() + */ + @Override + public void beginListItem() { + markNotEmpty(); + startContainerBlock(); + super.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) { + markNotEmpty(); + startContainerBlock(); + super.beginMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + markNotEmpty(); + startContainerBlock(); + super.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginSection(java.util.Map) + */ + @Override + public void beginSection(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginSection(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + super.endDocument(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + super.endDefinitionDescription(); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + super.endDefinitionList(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + super.endDefinitionTerm(); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingListener#endFormat(org.xwiki.rendering.listener.Format, java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + super.endFormat(format, parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(java.util.Map) + */ + @Override + public void endGroup(Map parameters) { + super.endGroup(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + super.endLink(reference, isFreeStandingURI, parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + super.endList(listType, parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + super.endListItem(); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, boolean isInline) { + super.endMacroMarker(name, parameters, content, isInline); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + super.endParagraph(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + super.endQuotation(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + super.endQuotationLine(); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + super.endSection(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + super.endHeader(level, id, parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + super.endTable(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + super.endTableCell(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + super.endTableHeadCell(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + super.endTableRow(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, + * org.xwiki.rendering.syntax.Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + super.onRawText(text, syntax); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + super.onEmptyLines(count); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + super.onHorizontalLine(parameters); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + super.onId(name); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + super.onImage(reference, isFreeStandingURI, parameters); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + super.onNewLine(); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpace() + */ + @Override + public void onSpace() { + super.onSpace(); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + super.onSpecialSymbol(symbol); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + super.onVerbatim(protectedString, isInline, parameters); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + super.onWord(word); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + super.onMacro(id, parameters, content, isInline); + markNotEmpty(); + } + + private void startContainerBlock() { + this.containerBlockStates.push(Boolean.TRUE); + } + + private void stopContainerBlock() { + this.containerBlockStates.pop(); + } + + private void markNotEmpty() { + if (!this.containerBlockStates.isEmpty() && this.containerBlockStates.peek()) { + this.containerBlockStates.pop(); + this.containerBlockStates.push(Boolean.FALSE); + } + } + +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EventType.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EventType.java new file mode 100644 index 000000000..e6014dd38 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EventType.java @@ -0,0 +1,408 @@ +/* + * 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.listener.chaining; + +import java.util.Map; + +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; + +/** + * Stores event types and offers a way to call a stored event. + * + * @version $Id$ + * @since 1.8RC1 + */ +public enum EventType { + + BEGIN_DOCUMENT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginDocument((Map) eventParameters[0]); + } + }, + END_DOCUMENT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endDocument((Map) eventParameters[0]); + } + }, + BEGIN_GROUP { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginGroup((Map) eventParameters[0]); + } + }, + END_GROUP { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endGroup((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_PARAGRAPH { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginParagraph((Map) eventParameters[0]); + } + }, + END_PARAGRAPH { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endParagraph((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_DEFINITION_LIST { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginDefinitionList((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + // This is because for nested definition lists, the event after a definition list item content + // is a new + // definition list + return true; + } + }, + END_DEFINITION_LIST { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endDefinitionList((Map) eventParameters[0]); + } + }, + BEGIN_DEFINITION_TERM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginDefinitionTerm(); + } + }, + END_DEFINITION_TERM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endDefinitionTerm(); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_DEFINITION_DESCRIPTION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginDefinitionDescription(); + } + }, + END_DEFINITION_DESCRIPTION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endDefinitionDescription(); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_FORMAT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginFormat((Format) eventParameters[0], (Map) eventParameters[1]); + } + }, + END_FORMAT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endFormat((Format) eventParameters[0], (Map) eventParameters[1]); + } + }, + BEGIN_HEADER { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginHeader((HeaderLevel) eventParameters[0], (String) eventParameters[1], + (Map) eventParameters[2]); + } + }, + END_HEADER { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endHeader((HeaderLevel) eventParameters[0], (String) eventParameters[1], + (Map) eventParameters[2]); + } + }, + BEGIN_LINK { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginLink((ResourceReference) eventParameters[0], (Boolean) eventParameters[1], + (Map) eventParameters[2]); + } + }, + END_LINK { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endLink((ResourceReference) eventParameters[0], (Boolean) eventParameters[1], + (Map) eventParameters[2]); + } + }, + BEGIN_LIST { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginList((ListType) eventParameters[0], (Map) eventParameters[1]); + } + + @Override + public boolean isInlineEnd() { + // This is because for nested lists, the event after list item content is a new list + return true; + } + }, + END_LIST { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endList((ListType) eventParameters[0], (Map) eventParameters[1]); + } + }, + BEGIN_LIST_ITEM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginListItem(); + } + }, + END_LIST_ITEM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endListItem(); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_MACRO_MARKER { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginMacroMarker((String) eventParameters[0], (Map) eventParameters[1], + (String) eventParameters[2], (Boolean) eventParameters[3]); + } + }, + END_MACRO_MARKER { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endMacroMarker((String) eventParameters[0], (Map) eventParameters[1], + (String) eventParameters[2], (Boolean) eventParameters[3]); + } + }, + BEGIN_QUOTATION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginQuotation((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + // This is because for nested quotations, the event after a quotation line is a new quotation + return true; + } + }, + END_QUOTATION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endQuotation((Map) eventParameters[0]); + } + }, + BEGIN_QUOTATION_LINE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginQuotationLine(); + } + }, + END_QUOTATION_LINE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endQuotationLine(); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_SECTION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginSection((Map) eventParameters[0]); + } + }, + END_SECTION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endSection((Map) eventParameters[0]); + } + }, + BEGIN_TABLE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginTable((Map) eventParameters[0]); + } + }, + END_TABLE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endTable((Map) eventParameters[0]); + } + }, + BEGIN_TABLE_CELL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginTableCell((Map) eventParameters[0]); + } + }, + END_TABLE_CELL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endTableCell((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_TABLE_HEAD_CELL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginTableHeadCell((Map) eventParameters[0]); + } + }, + END_TABLE_HEAD_CELL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endTableHeadCell((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_TABLE_ROW { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginTableRow((Map) eventParameters[0]); + } + }, + END_TABLE_ROW { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endTableRow((Map) eventParameters[0]); + } + }, + ON_RAW_TEXT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onRawText((String) eventParameters[0], (Syntax) eventParameters[1]); + } + }, + ON_EMPTY_LINES { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onEmptyLines((Integer) eventParameters[0]); + } + }, + ON_HORIZONTAL_LINE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onHorizontalLine((Map) eventParameters[0]); + } + }, + ON_ID { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onId((String) eventParameters[0]); + } + }, + ON_IMAGE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onImage((ResourceReference) eventParameters[0], (Boolean) eventParameters[1], + (Map) eventParameters[2]); + } + }, + ON_MACRO { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onMacro((String) eventParameters[0], (Map) eventParameters[1], + (String) eventParameters[2], (Boolean) eventParameters[3]); + } + }, + ON_NEW_LINE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onNewLine(); + } + }, + ON_SPACE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onSpace(); + } + }, + ON_SPECIAL_SYMBOL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onSpecialSymbol((Character) eventParameters[0]); + } + }, + ON_VERBATIM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onVerbatim((String) eventParameters[0], (Boolean) eventParameters[1], + (Map) eventParameters[2]); + } + }, + ON_WORD { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onWord((String) eventParameters[0]); + } + }; + + public abstract void fireEvent(Listener listener, Object[] eventParameters); + + public boolean isInlineEnd() { + return false; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/GroupStateChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/GroupStateChainingListener.java new file mode 100644 index 000000000..1d26ba5b2 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/GroupStateChainingListener.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.listener.chaining; + +import java.util.Map; + +/** + * Provides information on whether we're inside a group. Note that this listener is separated from + * the + * {@link org.xwiki.rendering.listener.chaining.BlockStateChainingListener} class because we don't + * want this listener to + * be stackable (since we need to create new instance of stackable listeners to reset states when we + * encounter a begin + * group event but we also need to know we're inside a group). + * + * @version $Id$ + * @since 1.8.3 + */ +public class GroupStateChainingListener extends AbstractChainingListener { + + private int groupDepth = 0; + + public GroupStateChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + public int getDocumentDepth() { + return this.groupDepth; + } + + public boolean isInGroup() { + return this.groupDepth > 0; + } + + // Events + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map) + */ + @Override + public void beginGroup(Map parameters) { + ++this.groupDepth; + + super.beginGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map) + */ + @Override + public void endGroup(Map parameters) { + super.endGroup(parameters); + + --this.groupDepth; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ListenerChain.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ListenerChain.java new file mode 100644 index 000000000..a99256e6f --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ListenerChain.java @@ -0,0 +1,172 @@ +/* + * 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.listener.chaining; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +/** + * Stores information about the listeners in the chain and the order in which they need to be + * called. Also sports a + * feature that allows pushing and popping listeners that are stackable. This feature is useful + * since listeners can hold + * stateful information and sometimes you may need to push new versions of them to start with new + * state information. For + * example this is used in the XWiki Syntax Renderer when group event is found to start the + * rendering for that group + * using reset state information. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class ListenerChain { + + /** + * The full list of chaining listeners. For each of them we have a stack since the ones that + * implement the + * {@link StackableChainingListener} interface can be stacked. + */ + private Map, Stack> listeners = new HashMap, Stack>(); + + /** + * The ordered list of listeners. We only allow one instance per listener class name so we just + * need to store the + * class object and then the instance can be found in {@link #listeners}. + */ + private List> nextListeners = new ArrayList>(); + + /** + * @param listener + * the chaining listener to add to the chain. If an instance of that listener is already + * present then we + * stack the new instance instead. + */ + public void addListener(ChainingListener listener) { + // If there's already an entry for that listener then push it on the existing stack + // and don't add the listener as an additional listener in the list (since it's already + // in there). We need to take these steps since the push() methods below will create + // new instances of listeners which will add themselves in the chain automatically. + Stack stack = this.listeners.get(listener.getClass()); + if (stack == null) { + stack = new Stack(); + this.listeners.put(listener.getClass(), stack); + this.nextListeners.add(listener.getClass()); + } + stack.push(listener); + } + + /** + * @param listenerClass + * the listener to remove from the chain + */ + public void removeListener(Class listenerClass) { + this.listeners.remove(listenerClass); + this.nextListeners.remove(listenerClass); + } + + /** + * @param listenerClass + * the listener for which we need to find the next listener in the chain + * @return the next listener in the chain + */ + public ChainingListener getNextListener(Class listenerClass) { + ChainingListener next = null; + int pos = indexOf(listenerClass); + if (pos > -1 && this.nextListeners.size() > pos + 1) { + next = this.listeners.get(this.nextListeners.get(pos + 1)).peek(); + } + return next; + } + + /** + * @param listenerClass + * the listener class for which we want to find the listener instance + * @return the listener instance corresponding to the passed class. Note that the last instance of + * the stack is + * returned + */ + public ChainingListener getListener(Class listenerClass) { + return this.listeners.get(listenerClass).peek(); + } + + /** + * @param listenerClass + * the listener class for which to find the position in the chain + * @return the position in the chain (first position is 0) + */ + public int indexOf(Class listenerClass) { + return this.nextListeners.indexOf(listenerClass); + } + + /** + * Create a new instance of the passed chaining listener if it's stackable (ie it implements the + * {@link org.xwiki.rendering.listener.chaining.StackableChainingListener} interface. This allows + * creating a clean + * state when some sub rendering has to be done with some new state. + * + * @param listenerClass + * the listener class for which to create a new instance (if stackable) + */ + public void pushListener(Class listenerClass) { + if (StackableChainingListener.class.isAssignableFrom(listenerClass)) { + Stack stack = this.listeners.get(listenerClass); + stack.push(((StackableChainingListener) stack.peek()).createChainingListenerInstance()); + } + } + + /** + * Create new instances of all chaining listeners that are stackable (ie that implement the + * {@link org.xwiki.rendering.listener.chaining.StackableChainingListener} interface. This allows + * creating a clean + * state when some sub rendering has to be done with some new state. + */ + public void pushAllStackableListeners() { + for (Class listenerClass : this.listeners.keySet()) { + pushListener(listenerClass); + } + } + + /** + * Remove all pushed stackable listeners to go back to the previous state (see + * {@link #pushAllStackableListeners()}. + */ + public void popAllStackableListeners() { + for (Class listenerClass : this.listeners.keySet()) { + popListener(listenerClass); + } + } + + /** + * Remove the last instance corresponding to the passed listener class if it's stackable, in order + * to go back to the + * previous state. + * + * @param listenerClass + * the class of the chaining listener to pop + */ + public void popListener(Class listenerClass) { + if (StackableChainingListener.class.isAssignableFrom(listenerClass)) { + this.listeners.get(listenerClass).pop(); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListener.java new file mode 100644 index 000000000..8c82d0528 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListener.java @@ -0,0 +1,630 @@ +/* + * 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.listener.chaining; + +import java.util.Map; + +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.QueueListener; +import org.xwiki.rendering.listener.QueueListener.Event; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Stores events without emitting them back in order to accumulate them and to provide a lookahead + * feature. The + * lookahead depth is configurable. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class LookaheadChainingListener extends AbstractChainingListener { + + private QueueListener previousEvents = new QueueListener(); + + private int lookaheadDepth; + + public LookaheadChainingListener(ListenerChain listenerChain, int lookaheadDepth) { + setListenerChain(listenerChain); + this.lookaheadDepth = lookaheadDepth; + } + + public Event getNextEvent() { + return getNextEvent(1); + } + + public Event getNextEvent(int depth) { + return this.previousEvents.getEvent(depth); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + this.previousEvents.beginDefinitionDescription(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + this.previousEvents.beginDefinitionList(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + this.previousEvents.beginDefinitionTerm(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + this.previousEvents.beginDocument(parameters); + flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map) + */ + @Override + public void beginGroup(Map parameters) { + this.previousEvents.beginGroup(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void beginFormat(Format format, Map parameters) { + this.previousEvents.beginFormat(format, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + this.previousEvents.beginHeader(level, id, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.previousEvents.beginLink(reference, isFreeStandingURI, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + this.previousEvents.beginList(listType, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginListItem() + */ + @Override + public void beginListItem() { + this.previousEvents.beginListItem(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) { + this.previousEvents.beginMacroMarker(name, parameters, content, isInline); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + this.previousEvents.beginParagraph(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + this.previousEvents.beginQuotation(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + this.previousEvents.beginQuotationLine(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginSection(java.util.Map) + */ + @Override + public void beginSection(Map parameters) { + this.previousEvents.beginSection(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + this.previousEvents.beginTable(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + this.previousEvents.beginTableCell(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + this.previousEvents.beginTableHeadCell(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + this.previousEvents.beginTableRow(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + this.previousEvents.endDefinitionDescription(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + this.previousEvents.endDefinitionList(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + this.previousEvents.endDefinitionTerm(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + this.previousEvents.endDocument(parameters); + flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map) + */ + public void endGroup(Map parameters) { + this.previousEvents.endGroup(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + this.previousEvents.endFormat(format, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + this.previousEvents.endHeader(level, id, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.previousEvents.endLink(reference, isFreeStandingURI, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + this.previousEvents.endList(listType, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + this.previousEvents.endListItem(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, boolean isInline) { + this.previousEvents.endMacroMarker(name, parameters, content, isInline); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + this.previousEvents.endParagraph(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + this.previousEvents.endQuotation(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + this.previousEvents.endQuotationLine(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + this.previousEvents.endSection(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + this.previousEvents.endTable(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + this.previousEvents.endTableCell(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + this.previousEvents.endTableHeadCell(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + this.previousEvents.endTableRow(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + this.previousEvents.onRawText(text, syntax); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + this.previousEvents.onEmptyLines(count); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + this.previousEvents.onHorizontalLine(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + this.previousEvents.onId(name); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.previousEvents.onImage(reference, isFreeStandingURI, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.previousEvents.onMacro(id, parameters, content, isInline); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + this.previousEvents.onNewLine(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpace() + */ + @Override + public void onSpace() { + this.previousEvents.onSpace(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + this.previousEvents.onSpecialSymbol(symbol); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.previousEvents.onVerbatim(protectedString, isInline, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + this.previousEvents.onWord(word); + firePreviousEvent(); + } + + private void firePreviousEvent() { + if (this.previousEvents.size() > this.lookaheadDepth) { + Event event = this.previousEvents.remove(); + event.eventType.fireEvent(getListenerChain().getNextListener(getClass()), event.eventParameters); + } + } + + private void flush() { + // Ensure that all remaining events are flushed + while (!this.previousEvents.isEmpty()) { + Event event = this.previousEvents.remove(); + event.eventType.fireEvent(getListenerChain().getNextListener(getClass()), event.eventParameters); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/StackableChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/StackableChainingListener.java new file mode 100644 index 000000000..8736f9c46 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/StackableChainingListener.java @@ -0,0 +1,38 @@ +/* + * 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.listener.chaining; + +/** + * A chaining listener that can be stacked in the {@link ListenerChain}. This is useful when a + * listener in the chain + * wants to reset all stackable listeners to a new state (for example when handling groups in the + * XWiki Syntax + * Renderer). + * + * @version $Id$ + * @since 1.8RC1 + */ +public interface StackableChainingListener extends ChainingListener { + + /** + * @return the new instance of the listener + */ + StackableChainingListener createChainingListenerInstance(); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/TextOnNewLineStateChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/TextOnNewLineStateChainingListener.java new file mode 100644 index 000000000..84bccc5f3 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/TextOnNewLineStateChainingListener.java @@ -0,0 +1,401 @@ +/* + * 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.listener.chaining; + +import java.util.Map; + +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.syntax.Syntax; + +/** + * Indicate if the text being written starts a new line. By text we mean Space, Special Symbol and + * Words. This is useful + * for some Renderers which need to have this information. For example the XWiki Syntax renderer + * uses it to decide + * whether to escape "*" characters starting new lines since otherwise they would be confused for + * list items. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class TextOnNewLineStateChainingListener extends AbstractChainingListener implements StackableChainingListener { + + private boolean isTextOnNewLine; + + public TextOnNewLineStateChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + /** + * {@inheritDoc} + * + * @see StackableChainingListener#createChainingListenerInstance() + */ + public StackableChainingListener createChainingListenerInstance() { + return new TextOnNewLineStateChainingListener(getListenerChain()); + } + + public boolean isTextOnNewLine() { + return this.isTextOnNewLine; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + this.isTextOnNewLine = false; + super.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + this.isTextOnNewLine = false; + super.beginDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + this.isTextOnNewLine = false; + super.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + this.isTextOnNewLine = false; + super.beginDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map) + */ + @Override + public void beginGroup(Map parameters) { + this.isTextOnNewLine = false; + super.beginGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void beginFormat(Format format, Map parameters) { + // This is an exception and a bit of a hack. The reason we're calling super before + // setting that we're no longer on a new line is for cases when we have "**" (BOLD) + // at the beginning of a line and we need to escape the following character if it's + // a space as otherwise it would be confused for a list. + super.beginFormat(format, parameters); + + this.isTextOnNewLine = false; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.isTextOnNewLine = false; + super.beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + this.isTextOnNewLine = false; + super.beginList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginListItem() + */ + @Override + public void beginListItem() { + this.isTextOnNewLine = false; + super.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, boolean isInline) { + this.isTextOnNewLine = false; + super.beginMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + this.isTextOnNewLine = true; + super.beginParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + this.isTextOnNewLine = false; + super.beginQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + this.isTextOnNewLine = false; + super.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + this.isTextOnNewLine = false; + super.beginHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + this.isTextOnNewLine = false; + super.beginTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + this.isTextOnNewLine = false; + super.beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + this.isTextOnNewLine = false; + super.beginTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + this.isTextOnNewLine = false; + super.beginTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, + * org.xwiki.rendering.syntax.Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + this.isTextOnNewLine = false; + super.onRawText(text, syntax); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + super.endLink(reference, isFreeStandingURI, parameters); + this.isTextOnNewLine = false; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + super.endParagraph(parameters); + this.isTextOnNewLine = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + super.endHeader(level, id, parameters); + this.isTextOnNewLine = false; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + super.endTable(parameters); + this.isTextOnNewLine = false; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + this.isTextOnNewLine = false; + super.onHorizontalLine(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + this.isTextOnNewLine = false; + super.onId(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map parameters) { + this.isTextOnNewLine = false; + super.onImage(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + super.onNewLine(); + this.isTextOnNewLine = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.isTextOnNewLine = false; + super.onMacro(id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.isTextOnNewLine = false; + super.onVerbatim(protectedString, isInline, parameters); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/AttachmentResourceReference.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/AttachmentResourceReference.java new file mode 100644 index 000000000..28e594476 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/AttachmentResourceReference.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.listener.reference; + +import org.apache.commons.lang.StringUtils; + +/** + * Represents a reference to an Attachment. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class AttachmentResourceReference extends ResourceReference { + + /** + * The name of the parameter representing the Query String. + */ + public static final String QUERY_STRING = "queryString"; + + /** + * @param reference + * see {@link #getReference()} + */ + public AttachmentResourceReference(String reference) { + super(reference, ResourceType.ATTACHMENT); + } + + /** + * @return the query string for specifying parameters that will be used in the rendered URL or + * null if no query + * string has been specified. Example: "mydata1=5&mydata2=Hello" + */ + public String getQueryString() { + return getParameter(QUERY_STRING); + } + + /** + * @param queryString + * see {@link #getQueryString()} + */ + public void setQueryString(String queryString) { + if (!StringUtils.isEmpty(queryString)) { + setParameter(QUERY_STRING, queryString); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/DocumentResourceReference.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/DocumentResourceReference.java new file mode 100644 index 000000000..e6e9c6279 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/DocumentResourceReference.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.listener.reference; + +import org.apache.commons.lang.StringUtils; + +/** + * Represents a reference to a Document. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class DocumentResourceReference extends ResourceReference { + + /** + * The name of the parameter representing the Query String. + */ + public static final String QUERY_STRING = "queryString"; + + /** + * The name of the parameter representing the Anchor. + */ + public static final String ANCHOR = "anchor"; + + /** + * @param reference + * see {@link #getReference()} + */ + public DocumentResourceReference(String reference) { + super(reference, ResourceType.DOCUMENT); + } + + /** + * @return the query string for specifying parameters that will be used in the rendered URL or + * null if no query + * string has been specified. Example: "mydata1=5&mydata2=Hello" + */ + public String getQueryString() { + return getParameter(QUERY_STRING); + } + + /** + * @param queryString + * see {@link #getQueryString()} + */ + public void setQueryString(String queryString) { + if (!StringUtils.isEmpty(queryString)) { + setParameter(QUERY_STRING, queryString); + } + } + + /** + * @return the anchor name pointing to an anchor defined in the referenced document or null if no + * anchor has been + * specified (in which case the reference points to the top of the document). Note that in + * XWiki anchors are + * automatically created for titles. Example: "TableOfContentAnchor" + */ + public String getAnchor() { + return getParameter(ANCHOR); + } + + /** + * @param anchor + * see {@link #getAnchor()} + */ + public void setAnchor(String anchor) { + if (!StringUtils.isEmpty(anchor)) { + setParameter(ANCHOR, anchor); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/InterWikiResourceReference.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/InterWikiResourceReference.java new file mode 100644 index 000000000..0253bcf31 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/InterWikiResourceReference.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.listener.reference; + +/** + * Represents a reference to an external wiki(Inter + * Wiki). An + * InterWiki reference is a shorthand notation to reference a set of external URL, all having a + * common prefix (eg + * http://server/some/common/prefix/a1, http://server/some/common/prefix/a2). An InterWiki reference + * is made of an + * InterWiki Alias which is a name corresponding to the common URL and an InterWiki Path which is + * the suffix to append + * to the common URL part to make the full URL. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class InterWikiResourceReference extends ResourceReference { + + /** + * The name of the parameter representing the InterWiki Alias. + */ + public static final String INTERWIKI_ALIAS = "interWikiAlias"; + + /** + * @param reference + * see {@link #getReference()} + */ + public InterWikiResourceReference(String reference) { + super(reference, ResourceType.INTERWIKI); + setTyped(true); + } + + /** + * @param interWikiAlias + * see {@link #getInterWikiAlias()} + */ + public void setInterWikiAlias(String interWikiAlias) { + setParameter(INTERWIKI_ALIAS, interWikiAlias); + } + + /** + * @return the Inter Wiki alias to which the + * resource is + * pointing to or null if not defined. Mappings between Inter Wiki aliases and actual + * locations are defined + * in the Inter Wiki Map. Example: "wikipedia" + */ + public String getInterWikiAlias() { + return getParameter(INTERWIKI_ALIAS); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceReference.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceReference.java new file mode 100644 index 000000000..8407ab6ad --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceReference.java @@ -0,0 +1,268 @@ +/* + * 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.listener.reference; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Represents a reference to a Resource (document, image, attachment, mail, etc). Note that this + * representation is + * independent of any wiki syntax. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class ResourceReference implements Cloneable { + + /** + * @see #isTyped() + */ + private boolean isTyped = true; + + /** + * @see #getReference() Note that the reason we store the reference as a String and not as an + * Entity Reference is + * because we want the Rendering module independent of the XWiki Model so that it can be used + * independently of + * XWiki. + */ + private String reference; + + /** + * @see #getType() + */ + private ResourceType type; + + /** + * @see #getParameter(String) + */ + private Map parameters = new HashMap(); + + /** + * @param reference + * see {@link #getReference()} + * @param type + * see {@link #getType()} + */ + public ResourceReference(String reference, ResourceType type) { + setReference(reference); + setType(type); + } + + /** + * @param isTyped + * see {@link #isTyped()} + */ + public void setTyped(boolean isTyped) { + this.isTyped = isTyped; + } + + /** + * @return true if the resource type has been explicitly provided (eg in XWiki Syntax 2.1 if the + * reference is + * prefixed with the resource type followed by ":" and then the rest of the reference) + */ + public boolean isTyped() { + return this.isTyped; + } + + /** + * @param reference + * see {@link #getReference()} + */ + public void setReference(String reference) { + this.reference = reference; + } + + /** + * @return the reference pointed to by this resource. For example a reference can be a document's + * name (which + * depends on the wiki, for example for XWiki the format is "wiki:space.page"), a URI (for + * example: + * mailto:john@doe.com), a URL, an Inter + * Wiki + * reference, etc + * @see #getType() + */ + public String getReference() { + return this.reference; + } + + /** + * @return the type of the resource + * @see ResourceType + */ + public ResourceType getType() { + return this.type; + } + + /** + * @param type + * the type of the resource + * @see ResourceType + */ + public void setType(ResourceType type) { + this.type = type; + } + + /** + * @param name + * see {@link #getParameter(String)} + * @param value + * see {@link #getParameter(String)} + */ + public void setParameter(String name, String value) { + this.parameters.put(name, value); + } + + /** + * @param parameters + * see {@link #getParameters()} + */ + public void setParameters(Map parameters) { + this.parameters.putAll(parameters); + } + + /** + * @param name + * see {@link #getParameter(String)} + */ + public void removeParameter(String name) { + this.parameters.remove(name); + } + + /** + * In order for Resource references to be extensible we allow for extra parameters in addition to + * the Resource + * reference. For example this is used in Document Resource References for storing the query + * string and anchor + * information, and in InterWiki Resource References to store the InterWiki Alias. Note that + * supported parameters + * depend on the Renderer that will be used (i.e. it depends on the target Syntax). For example + * the XWiki Syntax 2.1 + * only supports "queryString" and "anchor". + * + * @param name + * the name of the parameter to get + * @return the parameter value or null if no such parameter exist + */ + public String getParameter(String name) { + return this.parameters.get(name); + } + + /** + * @return the collections of parameters, see {@link #getParameter(String)} + */ + public Map getParameters() { + return Collections.unmodifiableMap(this.parameters); + } + + /** + * {@inheritDoc} + *

+ * The output is syntax independent since this class is used for all syntaxes. Specific syntaxes + * should extend this + * class and override this method to perform syntax-dependent formatting. + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("Typed = [").append(isTyped()).append("]"); + sb.append(" "); + sb.append("Type = [").append(getType().getScheme()).append("]"); + if (getReference() != null) { + sb.append(" "); + sb.append("Reference = [").append(getReference()).append("]"); + } + Map params = getParameters(); + if (!params.isEmpty()) { + sb.append(" "); + sb.append("Parameters = ["); + Iterator> it = params.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + sb.append("[").append(entry.getKey()).append("] = [").append(entry.getValue()).append("]"); + if (it.hasNext()) { + sb.append(", "); + } + } + sb.append("]"); + } + + return sb.toString(); + } + + /** + * {@inheritDoc} + * + * @see Object#clone() + */ + @Override + public ResourceReference clone() { + ResourceReference clone; + try { + clone = (ResourceReference) super.clone(); + } catch (CloneNotSupportedException e) { + // Should never happen + throw new RuntimeException("Failed to clone object", e); + } + return clone; + } + + /** + * {@inheritDoc} + * + * @see Object#hashCode() + */ + @Override + public int hashCode() { + return new HashCodeBuilder(1, 9).append(getType()).append(isTyped()).append(getReference()) + .append(getParameters()).toHashCode(); + } + + /** + * {@inheritDoc} + * + * @see Object#equals(Object) + */ + @Override + public boolean equals(Object object) { + if (object == null) { + return false; + } + if (object == this) { + return true; + } + if (object.getClass() != getClass()) { + return false; + } + ResourceReference rhs = (ResourceReference) object; + return new EqualsBuilder().append(getType(), rhs.getType()).append(isTyped(), rhs.isTyped()) + .append(getReference(), rhs.getReference()).append(getParameters(), rhs.getParameters()).isEquals(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceType.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceType.java new file mode 100644 index 000000000..eefdf8329 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceType.java @@ -0,0 +1,152 @@ +/* + * 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.listener.reference; + +/** + * The Resource type. It can be one of: + *

    + *
  • document ("doc")
  • + *
  • URL ("url")
  • + *
  • document in another wiki (interwiki) ("interwiki")
  • + *
  • relative URL ("path")
  • + *
  • mail ("mailto")
  • + *
  • attachment ("attach")
  • + *
  • UNC path ("unc")
  • + *
+ * + * @version $Id$ + * @since 2.5RC1 + */ +public class ResourceType { + + /** + * Special type to be used when the type of the resource is not known. + */ + public static final ResourceType UNKNOWN = new ResourceType("unknown"); + + /** + * Represents a Document. + */ + public static final ResourceType DOCUMENT = new ResourceType("doc"); + + /** + * Represents an URL. + */ + public static final ResourceType URL = new ResourceType("url"); + + /** + * Represents a document in another wiki. + */ + public static final ResourceType INTERWIKI = new ResourceType("interwiki"); + + /** + * Represents a relative URL in the current wiki. + */ + public static final ResourceType PATH = new ResourceType("path"); + + /** + * Represents a mail. + */ + public static final ResourceType MAILTO = new ResourceType("mailto"); + + /** + * Represents an attachment. + */ + public static final ResourceType ATTACHMENT = new ResourceType("attach"); + + /** + * Represents an icon. + */ + public static final ResourceType ICON = new ResourceType("icon"); + + /** + * Represents a UNC (Universal Naming Convention) (eg "\\myserver\myshare\mydoc.txt"). + * + * @since 2.7M1 + */ + public static final ResourceType UNC = new ResourceType("unc"); + + /** + * @see #getScheme() + */ + private String scheme; + + /** + * @param scheme + * see {@link #getScheme()} + */ + public ResourceType(String scheme) { + setScheme(scheme); + } + + /** + * @return the type of the link (eg "doc" for links to documents, etc) + */ + public String getScheme() { + return this.scheme; + } + + /** + * @param scheme + * see {@link #getScheme()} + */ + public void setScheme(String scheme) { + this.scheme = scheme; + } + + /** + * {@inheritDoc} + * + * @see Object#hashCode() + */ + @Override + public int hashCode() { + // Random number. See http://www.technofundo.com/tech/java/equalhash.html for the detail of this + // algorithm. + int hash = 8; + hash = 31 * hash + (null == getScheme() ? 0 : getScheme().hashCode()); + return hash; + } + + /** + * {@inheritDoc} + * + * @see Object#equals(Object) + */ + @Override + public boolean equals(Object object) { + boolean result; + + // See http://www.technofundo.com/tech/java/equalhash.html for the detail of this algorithm. + if (this == object) { + result = true; + } else { + if ((object == null) || (object.getClass() != this.getClass())) { + result = false; + } else { + // object must be ResourceType at this point + ResourceType type = (ResourceType) object; + result = (getScheme() == type.getScheme() + || (getScheme() != null && getScheme().equals(type.getScheme()))); + } + } + return result; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ParseException.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ParseException.java new file mode 100644 index 000000000..11ba5e565 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ParseException.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.parser; + +/** + * Encapsulate a parsing error. + * + * @version $Id$ + */ +public class ParseException extends Exception { + + /** + * Class ID for serialization. + */ + private static final long serialVersionUID = 442523704445037944L; + + /** + * 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 ParseException(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 ParseException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/Parser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/Parser.java new file mode 100644 index 000000000..6b2b40518 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/Parser.java @@ -0,0 +1,52 @@ +/* + * 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.parser; + +import java.io.Reader; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Parse content into a XDOM (a tree of {@link org.xwiki.rendering.block.Block}s). + * + * @version $Id$ + * @since 1.5M2 + */ +@ComponentRole +public interface Parser { + + /** + * @return the wiki syntax the parser is implementing + */ + Syntax getSyntax(); + + /** + * @param source + * the content to parse + * @return the tree representation of the content as {@link org.xwiki.rendering.block.Block}s + * @throws ParseException + * if the source cannot be read or an unexpected error happens during the parsing. + * Parsers should be + * written to not generate any error as much as possible. + */ + XDOM parse(Reader source) throws ParseException; +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceParser.java new file mode 100644 index 000000000..cfe1b9e79 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceParser.java @@ -0,0 +1,47 @@ +/* + * 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.parser; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Interface for parsing resource references (references to links, images, attachments, etc) for + * various wiki syntaxes. + * + * @version $Id$ + * @since 2.5RC1 + */ +@ComponentRole +public interface ResourceReferenceParser { + + /** + * Parses a resource reference represented (reference to a link, image, attachment, etc) as a + * String into a + * {@link org.xwiki.rendering.listener.reference.ResourceReference} object. + * + * @param rawReference + * the string representation of the resource reference to parse (the supported syntax + * depends on the + * parser implementation used) + * @return the parsed resource reference + */ + ResourceReference parse(String rawReference); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceTypeParser.java new file mode 100644 index 000000000..f7ac2fb02 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceTypeParser.java @@ -0,0 +1,49 @@ +/* + * 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.parser; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; + +/** + * Parses a raw Resource Reference by determining if it has the right type and return a non-null + * {@link org.xwiki.rendering.listener.reference.ResourceReference} object if it has. + * + * @version $Id$ + * @since 2.5RC1 + */ +@ComponentRole +public interface ResourceReferenceTypeParser { + + /** + * @return the resource type (document, url, attachment, etc). + */ + ResourceType getType(); + + /** + * @param reference + * the raw resource reference to parse + * @return the parsed resource information if the passed reference can be parsed by this type + * parser or null if the + * passed reference isn't valid + */ + ResourceReference parse(String reference); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/StreamParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/StreamParser.java new file mode 100644 index 000000000..e36422e6d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/StreamParser.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.parser; + +import java.io.Reader; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Streaming based parser. Instead of returning a resulting XDOM it send events during the parsing. + * + * @version $Id$ + * @since 2.1M1 + */ +@ComponentRole +public interface StreamParser { + + /** + * @return the wiki syntax the parser is implementing + */ + Syntax getSyntax(); + + /** + * @param source + * the content to parse + * @param listener + * receive event for each element + * @throws ParseException + * if the source cannot be read or an unexpected error happens during the parsing. + * Parsers should be + * written to not generate any error as much as possible. + */ + void parse(Reader source, Listener listener) throws ParseException; +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/AbstractChainingPrintRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/AbstractChainingPrintRenderer.java new file mode 100644 index 000000000..b24fe9fa5 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/AbstractChainingPrintRenderer.java @@ -0,0 +1,94 @@ +/* + * 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.renderer; + +import java.util.Stack; + +import org.xwiki.rendering.listener.chaining.AbstractChainingListener; +import org.xwiki.rendering.listener.chaining.ChainingListener; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * @version $Id$ + * @since 1.8RC1 + */ +public abstract class AbstractChainingPrintRenderer extends AbstractChainingListener implements PrintRenderer { + + /** + * The printer stack. Can be used to print in a specific printer and then easily return to the + * previous one. + */ + private Stack printers = new Stack(); + + /** + * @return the main printer. + */ + public WikiPrinter getMainPrinter() { + return this.printers.firstElement(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.PrintRenderer#getPrinter() + */ + public WikiPrinter getPrinter() { + return this.printers.peek(); + } + + /** + * {@inheritDoc} + * + * @see PrintRenderer#setPrinter(org.xwiki.rendering.renderer.printer.WikiPrinter) + * @since 2.0M3 + */ + public void setPrinter(WikiPrinter printer) { + pushPrinter(printer); + } + + /** + * Change the current {@link WikiPrinter} with the provided one. + * + * @param wikiPrinter + * the new {@link WikiPrinter} to use + */ + protected void pushPrinter(WikiPrinter wikiPrinter) { + this.printers.push(wikiPrinter); + + // Since we're setting a new printer to use, make sure that all print renderers in the chain + // have the new + // printer set. Only do this if we're on the top level Print Renderer. + if (getListenerChain().indexOf(getClass()) == 0) { + ChainingListener nextListener = this; + while ((nextListener = getListenerChain().getNextListener(nextListener.getClass())) != null) { + if (PrintRenderer.class.isAssignableFrom(nextListener.getClass())) { + ((PrintRenderer) nextListener).setPrinter(wikiPrinter); + } + } + } + } + + /** + * Removes the current {@link WikiPrinter} and instead sets the previous printer as active. + */ + protected void popPrinter() { + this.printers.pop(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/BlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/BlockRenderer.java new file mode 100644 index 000000000..581fa947c --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/BlockRenderer.java @@ -0,0 +1,52 @@ +/* + * 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.renderer; + +import java.util.Collection; +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.renderer.printer.WikiPrinter; +import org.xwiki.rendering.block.Block; + +/** + * Renders a {@link Block} in some target syntax. + * + * @version $Id$ + * @since 2.0M3 + */ +@ComponentRole +public interface BlockRenderer { + + /** + * @param block + * the block to render in the target syntax + * @param printer + * the object where to output the result of the rendering + */ + void render(Block block, WikiPrinter printer); + + /** + * @param blocks + * the list of blocks to render in the target syntax + * @param printer + * the object where to output the result of the rendering + * @todo remove this API once we introduce the notion of BlockCollection + */ + void render(Collection blocks, WikiPrinter printer); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRenderer.java new file mode 100644 index 000000000..041379d27 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRenderer.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.renderer; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * A Print Renderer is a {@link Renderer} that outputs its results to a {@link WikiPrinter}. + * + * @version $Id$ + * @since 1.6M1 + */ +@ComponentRole +public interface PrintRenderer extends Renderer { + + /** + * @return the printer to which events generate results in. For example the XHTML print renderer + * outputs XHTML to a + * {@link WikiPrinter} and the resulting XHTML can be retrieved by calling + * {@link org.xwiki.rendering.renderer.printer.WikiPrinter#toString()} + */ + WikiPrinter getPrinter(); + + /** + * @param printer + * the wiki printer to use when the Renderer needs to output rendered content + * @since 2.0M3 + */ + void setPrinter(WikiPrinter printer); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRendererFactory.java new file mode 100644 index 000000000..f69353464 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRendererFactory.java @@ -0,0 +1,54 @@ +/* + * 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.renderer; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * Allows creating {@link Renderer}s of a given type (one factory implementation per Renderer type). + * We need a factory + * since we need to pass a {@link WikiPrinter} object to the created Renderer. In addition this + * factory allows us to be + * able to return the {@link org.xwiki.rendering.syntax.Syntax} supported by the Renderer without + * needing to create an + * instance of it. + * + * @version $Id$ + * @since 1.6M2 + */ +@ComponentRole +public interface PrintRendererFactory { + + /** + * @return the Syntax supported by the Renderer type + * @since 2.0M3 + */ + Syntax getSyntax(); + + /** + * @param printer + * the printer to use to output renderer data + * @return a new Renderer instance (stateful) + * @since 2.0M3 + */ + PrintRenderer createRenderer(WikiPrinter printer); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/Renderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/Renderer.java new file mode 100644 index 000000000..646e64312 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/Renderer.java @@ -0,0 +1,31 @@ +/* + * 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.renderer; + +import org.xwiki.rendering.listener.Listener; + +/** + * A special type of Listener which writes data somewhere. For example, a PDFRenderer, an + * XHTMLRenderer, etc. + * + * @version $Id$ + * @since 1.5M2 + */ +public interface Renderer extends Listener {} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/DefaultWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/DefaultWikiPrinter.java new file mode 100644 index 000000000..ae67e50e4 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/DefaultWikiPrinter.java @@ -0,0 +1,100 @@ +/* + * 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.renderer.printer; + +/** + * Printer using a {@link StringBuffer} as the underlying output target. + * + * @version $Id$ + * @since 1.6M1 + */ +public class DefaultWikiPrinter implements WikiPrinter { + + /** + * The buffer where to put the provided {@link String}s. + */ + private StringBuffer buffer; + + /** + * The default constructor. It initialize a new empty {@link StringBuffer}. + */ + public DefaultWikiPrinter() { + this(new StringBuffer()); + } + + /** + * @param buffer + * the {@link StringBuffer} to where to put the provided {@link String}s. + */ + public DefaultWikiPrinter(StringBuffer buffer) { + this.buffer = buffer; + } + + /** + * @return the buffer containing the printed {@link String}s. + */ + public StringBuffer getBuffer() { + return this.buffer; + } + + /** + * This method is protected to allow classes extending this one to override what a new line is. + * + * @return a new line symbols + */ + protected String getEOL() { + return "\n"; + } + + /** + * {@inheritDoc} + * + * @see WikiPrinter#print(String) + */ + public void print(String text) { + getBuffer().append(text); + } + + /** + * {@inheritDoc} + * + * @see WikiPrinter#println(String) + */ + public void println(String text) { + getBuffer().append(text).append(getEOL()); + } + + /** + * {@inheritDoc} + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getBuffer().toString(); + } + + /** + * Removes the buffer's content which allows the printer to be reused. + */ + public void clear() { + getBuffer().setLength(0); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/LookaheadWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/LookaheadWikiPrinter.java new file mode 100644 index 000000000..e30df5107 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/LookaheadWikiPrinter.java @@ -0,0 +1,87 @@ +/* + * 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.renderer.printer; + +/** + * Wiki printer that allows deferring printing text and that instead can save it in some internal + * buffer. This allows + * accumulating some content before it's flushed. This feature is used for example in the XWiki + * Syntax Renderer to + * accumulate text so that it be reviewed and escaped before printed (indeed some text has some + * characters that need to + * be escaped or they'd have a wiki meaning otherwise). + * + * @version $Id$ + * @since 1.7 + */ +public class LookaheadWikiPrinter extends WrappingWikiPrinter { + + private StringBuffer buffer = new StringBuffer(); + + public LookaheadWikiPrinter(WikiPrinter printer) { + super(printer); + } + + protected void printInternal(String text) { + super.print(text); + } + + protected void printlnInternal(String text) { + super.println(text); + } + + public void print(String text) { + flush(); + printInternal(text); + } + + public void println(String text) { + flush(); + printlnInternal(text); + } + + public void printDelayed(String text) { + getBuffer().append(text); + } + + public void printlnDelayed(String text) { + getBuffer().append(text).append(getEOL()); + } + + public StringBuffer getBuffer() { + return this.buffer; + } + + public void flush() { + if (getBuffer().length() > 0) { + printInternal(getBuffer().toString()); + getBuffer().setLength(0); + } + } + + /** + * This method is protected to allow classes extending this one to define what a new line is. + * + * @return a new line symbols + */ + protected String getEOL() { + return "\n"; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/VoidWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/VoidWikiPrinter.java new file mode 100644 index 000000000..7a5d953aa --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/VoidWikiPrinter.java @@ -0,0 +1,56 @@ +/* + * 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.renderer.printer; + +/** + * A WikiPrinter implementation which does not do anything. + * + * @version $Id$ + */ +public class VoidWikiPrinter implements WikiPrinter { + + /** + * Unique instance of {@link VoidWikiPrinter}. + */ + public static final VoidWikiPrinter VOIDWIKIPRINTER = new VoidWikiPrinter(); + + /** + * Use {@link #VOIDWIKIPRINTER}. + */ + private VoidWikiPrinter() {} + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.WikiPrinter#print(java.lang.String) + */ + public void print(String text) { + // Don't do anything + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.WikiPrinter#println(java.lang.String) + */ + public void println(String text) { + // Don't do anything + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WikiPrinter.java new file mode 100644 index 000000000..5482a0998 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WikiPrinter.java @@ -0,0 +1,41 @@ +/* + * 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.renderer.printer; + +/** + * Printer for {@link org.xwiki.rendering.renderer.PrintRenderer}s. + * + * @version $Id$ + * @since 1.6M1 + */ +public interface WikiPrinter { + + /** + * @param text + * print the provided {@link String}. + */ + void print(String text); + + /** + * @param text + * print the provided {@link String} and add a new line. + */ + void println(String text); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WrappingWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WrappingWikiPrinter.java new file mode 100644 index 000000000..e87a58f4f --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WrappingWikiPrinter.java @@ -0,0 +1,52 @@ +/* + * 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.renderer.printer; + +/** + * Wraps a wiki printer. + * + * @version $Id$ + * @since 1.7 + */ +public class WrappingWikiPrinter implements WikiPrinter { + + private WikiPrinter printer; + + public WrappingWikiPrinter(WikiPrinter printer) { + this.printer = printer; + } + + public void print(String text) { + getWrappedPrinter().print(text); + } + + public void println(String text) { + getWrappedPrinter().println(text); + } + + public WikiPrinter getWrappedPrinter() { + return this.printer; + } + + @Override + public String toString() { + return getWrappedPrinter().toString(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java new file mode 100644 index 000000000..eb5428ab5 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java @@ -0,0 +1,269 @@ +/* + * 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.renderer.printer; + +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.xml.sax.Attributes; + +/** + * Base toolkit class for all XHTML-based renderers. This printer handles whitespaces so that it + * prints " " when + * needed (i.e. when the spaces are at the beginning or at the end of an element's content or when + * there are more than 1 + * contiguous spaces, except for CDATA sections and inside PRE elements. It also knows how to handle + * XHTML comments). + * + * @version $Id$ + * @since 1.7M1 + */ +public class XHTMLWikiPrinter extends XMLWikiPrinter { + + private int spaceCount = 0; + + private boolean isInCData; + + private boolean isInPreserveElement; + + private boolean elementEnded; + + private boolean hasTextBeenPrinted; + + /** + * @param printer + * the object to which to write the XHTML output to + */ + public XHTMLWikiPrinter(WikiPrinter printer) { + super(printer); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXML(java.lang.String) + */ + @Override + public void printXML(String str) { + handleSpaceWhenInText(); + super.printXML(str); + this.hasTextBeenPrinted = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLElement(java.lang.String) + */ + @Override + public void printXMLElement(String name) { + handleSpaceWhenStartElement(); + super.printXMLElement(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLElement(java.lang.String, + * java.lang.String[][]) + */ + @Override + public void printXMLElement(String name, String[][] attributes) { + handleSpaceWhenStartElement(); + super.printXMLElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLElement(java.lang.String, + * java.util.Map) + */ + @Override + public void printXMLElement(String name, Map attributes) { + handleSpaceWhenStartElement(); + super.printXMLElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartElement(java.lang.String) + */ + @Override + public void printXMLStartElement(String name) { + handleSpaceWhenStartElement(); + super.printXMLStartElement(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartElement(java.lang.String, + * java.lang.String[][]) + */ + @Override + public void printXMLStartElement(String name, String[][] attributes) { + handleSpaceWhenStartElement(); + super.printXMLStartElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartElement(java.lang.String, + * java.util.Map) + */ + @Override + public void printXMLStartElement(String name, Map attributes) { + handleSpaceWhenStartElement(); + super.printXMLStartElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartElement(java.lang.String, + * org.xml.sax.Attributes) + */ + @Override + public void printXMLStartElement(String name, Attributes attributes) { + handleSpaceWhenStartElement(); + super.printXMLStartElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLEndElement(java.lang.String) + */ + @Override + public void printXMLEndElement(String name) { + handleSpaceWhenEndlement(); + super.printXMLEndElement(name); + this.elementEnded = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLComment(java.lang.String) + */ + @Override + public void printXMLComment(String content) { + printXMLComment(content, false); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLComment(java.lang.String, + * boolean) + */ + @Override + public void printXMLComment(String content, boolean escape) { + handleSpaceWhenStartElement(); + super.printXMLComment(content, escape); + this.elementEnded = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartCData() + */ + @Override + public void printXMLStartCData() { + handleSpaceWhenStartElement(); + super.printXMLStartCData(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLEndCData() + */ + @Override + public void printXMLEndCData() { + handleSpaceWhenEndlement(); + super.printXMLEndCData(); + } + + /** + * This method should be used to print a space rather than calling printXML(" "). + */ + public void printSpace() { + this.spaceCount++; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printRaw(java.lang.String) + */ + @Override + public void printRaw(String raw) { + handleSpaceWhenStartElement(); + super.printRaw(raw); + this.elementEnded = true; + } + + private void handleSpaceWhenInText() { + if (this.elementEnded || this.hasTextBeenPrinted) { + handleSpaceWhenStartElement(); + } else { + handleSpaceWhenEndlement(); + } + } + + private void handleSpaceWhenStartElement() { + // Use case: something ... + // Use case: something + + +

Represents content elements (Paragraph, Header, List, Styles, + etc) as Blocks and a full document content is represented by a XDOM + object.

+ +

Related Documentation

+

For overviews, tutorials, examples, guides, and tool + documentation, please see:

+ + \ No newline at end of file diff --git a/celements-xwiki-rendering-api/src/main/resources/META-INF/components.txt b/celements-xwiki-rendering-api/src/main/resources/META-INF/components.txt new file mode 100644 index 000000000..8a68b5047 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/resources/META-INF/components.txt @@ -0,0 +1,63 @@ +org.xwiki.rendering.internal.parser.PlainTextBlockParser +org.xwiki.rendering.internal.parser.PlainTextStreamParser +org.xwiki.rendering.internal.parser.reference.GenericLinkReferenceParser +org.xwiki.rendering.internal.parser.reference.GenericImageReferenceParser +org.xwiki.rendering.internal.parser.reference.DefaultResourceReferenceParser +org.xwiki.rendering.internal.parser.reference.DefaultLinkReferenceParser +org.xwiki.rendering.internal.parser.reference.DefaultImageReferenceParser +org.xwiki.rendering.internal.parser.reference.DefaultUntypedLinkReferenceParser +org.xwiki.rendering.internal.parser.reference.DefaultUntypedImageReferenceParser +org.xwiki.rendering.internal.parser.reference.XWiki20LinkReferenceParser +org.xwiki.rendering.internal.parser.reference.XWiki20ImageReferenceParser +org.xwiki.rendering.internal.parser.reference.DocumentResourceReferenceTypeParser +org.xwiki.rendering.internal.parser.reference.InterWikiResourceReferenceTypeParser +org.xwiki.rendering.internal.parser.reference.URLResourceReferenceTypeParser +org.xwiki.rendering.internal.parser.reference.MailtoResourceReferenceTypeParser +org.xwiki.rendering.internal.parser.reference.AttachmentResourceReferenceTypeParser +org.xwiki.rendering.internal.parser.reference.PathResourceReferenceTypeParser +org.xwiki.rendering.internal.parser.reference.IconResourceReferenceTypeParser +org.xwiki.rendering.internal.parser.reference.UNCResourceReferenceTypeParser +org.xwiki.rendering.internal.renderer.DefaultLinkLabelGenerator +org.xwiki.rendering.internal.renderer.DefaultAttachmentURILabelGenerator +org.xwiki.rendering.internal.renderer.MailtoURILabelGenerator +org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxRenderer +org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxBlockRenderer +org.xwiki.rendering.internal.renderer.xwiki20.XWikiSyntaxRendererFactory +org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxLinkReferenceSerializer +org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxImageReferenceSerializer +org.xwiki.rendering.internal.renderer.xwiki20.reference.DefaultResourceReferenceTypeSerializer +org.xwiki.rendering.internal.renderer.xwiki20.reference.DocumentReferenceTypeSerializer +org.xwiki.rendering.internal.renderer.xwiki20.reference.InterWikiReferenceTypeSerializer +org.xwiki.rendering.internal.renderer.xwiki21.XWikiSyntaxRenderer +org.xwiki.rendering.internal.renderer.xwiki21.XWikiSyntaxBlockRenderer +org.xwiki.rendering.internal.renderer.xwiki21.XWikiSyntaxRendererFactory +org.xwiki.rendering.internal.renderer.xwiki21.reference.XWikiSyntaxLinkReferenceSerializer +org.xwiki.rendering.internal.renderer.xwiki21.reference.XWikiSyntaxImageReferenceSerializer +org.xwiki.rendering.internal.renderer.xwiki21.reference.InterWikiReferenceTypeSerializer +org.xwiki.rendering.internal.renderer.xhtml.XHTMLRendererFactory +org.xwiki.rendering.internal.renderer.xhtml.XHTMLRenderer +org.xwiki.rendering.internal.renderer.xhtml.XHTMLBlockRenderer +org.xwiki.rendering.internal.renderer.xhtml.AnnotatedXHTMLRendererFactory +org.xwiki.rendering.internal.renderer.xhtml.AnnotatedXHTMLRenderer +org.xwiki.rendering.internal.renderer.xhtml.AnnotatedXHTMLBlockRenderer +org.xwiki.rendering.internal.renderer.xhtml.image.DefaultXHTMLImageRenderer +org.xwiki.rendering.internal.renderer.xhtml.image.AnnotatedXHTMLImageRenderer +org.xwiki.rendering.internal.renderer.xhtml.link.AnnotatedXHTMLLinkRenderer +org.xwiki.rendering.internal.renderer.xhtml.link.DefaultXHTMLLinkRenderer +org.xwiki.rendering.internal.renderer.xhtml.link.DefaultXHTMLLinkTypeRenderer +org.xwiki.rendering.internal.renderer.xhtml.link.MailtoXHTMLLinkTypeRenderer +org.xwiki.rendering.internal.renderer.xhtml.link.InterWikiXHTMLLinkTypeRenderer +org.xwiki.rendering.internal.renderer.xhtml.link.DocumentXHTMLLinkTypeRenderer +org.xwiki.rendering.internal.renderer.xhtml.link.AttachmentXHTMLLinkTypeRenderer +org.xwiki.rendering.internal.renderer.xhtml.link.UNCXHTMLLinkTypeRenderer +org.xwiki.rendering.internal.renderer.xhtml.XHTMLMarkerResourceReferenceSerializer +org.xwiki.rendering.internal.renderer.event.EventRendererFactory +org.xwiki.rendering.internal.renderer.event.EventRenderer +org.xwiki.rendering.internal.renderer.event.EventBlockRenderer +org.xwiki.rendering.internal.renderer.plain.PlainTextRendererFactory +org.xwiki.rendering.internal.renderer.plain.PlainTextRenderer +org.xwiki.rendering.internal.renderer.plain.PlainTextBlockRenderer +org.xwiki.rendering.internal.converter.DefaultConverter +org.xwiki.rendering.internal.transformation.DefaultTransformationManager +org.xwiki.rendering.internal.configuration.DefaultRenderingConfiguration +org.xwiki.rendering.internal.syntax.DefaultSyntaxFactory \ No newline at end of file diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/block/BlockTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/block/BlockTest.java new file mode 100644 index 000000000..0f25ff853 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/block/BlockTest.java @@ -0,0 +1,215 @@ +/* + * 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.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.DocumentResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; + +/** + * Unit tests for Block manipulation, testing {@link AbstractBlock}. + * + * @version $Id$ + * @since 1.5M2 + */ +public class BlockTest { + + @Test + public void testGetBlocksByType() { + ParagraphBlock pb1 = new ParagraphBlock(Arrays + .asList(new HeaderBlock(Arrays.asList(new WordBlock("title1")), HeaderLevel.LEVEL1))); + ParagraphBlock pb2 = new ParagraphBlock(Arrays + .asList(new HeaderBlock(Arrays.asList(new WordBlock("title2")), HeaderLevel.LEVEL2))); + ParagraphBlock pb3 = new ParagraphBlock(Arrays.asList(pb1, pb2)); + + List results = pb1.getChildrenByType(HeaderBlock.class, true); + Assert.assertEquals(1, results.size()); + + results = pb3.getChildrenByType(HeaderBlock.class, true); + Assert.assertEquals(2, results.size()); + } + + @Test + public void testInsertChildAfter() { + Block wb1 = new WordBlock("block1"); + Block wb2 = new WordBlock("block2"); + ParagraphBlock pb = new ParagraphBlock(Arrays.asList(wb1, wb2)); + + Block wb = new WordBlock("block"); + + pb.insertChildAfter(wb, wb1); + Assert.assertSame(wb, pb.getChildren().get(1)); + Assert.assertSame(wb1, wb.getPreviousSibling()); + Assert.assertSame(wb2, wb.getNextSibling()); + Assert.assertSame(wb, wb1.getNextSibling()); + Assert.assertSame(wb, wb2.getPreviousSibling()); + + pb.insertChildAfter(wb, wb2); + Assert.assertSame(wb, pb.getChildren().get(3)); + Assert.assertSame(wb2, wb.getPreviousSibling()); + Assert.assertSame(wb, wb2.getNextSibling()); + Assert.assertNull(wb.getNextSibling()); + } + + @Test + public void testInsertChildBefore() { + Block wb1 = new WordBlock("block1"); + Block wb2 = new WordBlock("block2"); + + List children = new ArrayList<>(); + children.add(wb1); + children.add(wb2); + + ParagraphBlock pb = new ParagraphBlock(children); + + Block wb = new WordBlock("block"); + + pb.insertChildBefore(wb, wb1); + Assert.assertSame(wb, pb.getChildren().get(0)); + + pb.insertChildBefore(wb, wb2); + Assert.assertSame(wb, pb.getChildren().get(2)); + } + + @Test + public void testReplaceBlock() { + // It's important all blocks have same content to make sure replacement api don't find the + // position of the + // old block using Object#equals + Block word1 = new WordBlock("block1"); + Block word2 = new WordBlock("block2"); + Block word3 = new WordBlock("block3"); + + Block parentBlock = new ParagraphBlock(Arrays.asList(word1, word2)); + + // replace by one + parentBlock.replaceChild(word3, word1); + + Assert.assertEquals(2, parentBlock.getChildren().size()); + Assert.assertSame(word3, parentBlock.getChildren().get(0)); + Assert.assertSame(word2, parentBlock.getChildren().get(1)); + Assert.assertSame(word2, word3.getNextSibling()); + Assert.assertSame(word3, word2.getPreviousSibling()); + + // replace by nothing + parentBlock.replaceChild(Collections.emptyList(), word2); + + Assert.assertEquals(1, parentBlock.getChildren().size()); + Assert.assertSame(word3, parentBlock.getChildren().get(0)); + Assert.assertNull(word3.getNextSibling()); + Assert.assertNull(word3.getPreviousSibling()); + + // replace by several + parentBlock.replaceChild(Arrays.asList(word1, word2), word3); + + Assert.assertEquals(2, parentBlock.getChildren().size()); + Assert.assertSame(word1, parentBlock.getChildren().get(0)); + Assert.assertSame(word2, parentBlock.getChildren().get(1)); + Assert.assertSame(word2, word1.getNextSibling()); + Assert.assertSame(word1, word2.getPreviousSibling()); + + // provide not existing block to replace + try { + parentBlock.replaceChild(word3, new WordBlock("not existing")); + Assert.fail("Should have thrown an InvalidParameterException exception"); + } catch (InvalidParameterException expected) { + // expected + } + } + + @Test + public void testClone() { + WordBlock wb = new WordBlock("block"); + ImageBlock ib = new ImageBlock(new ResourceReference("document@attachment", ResourceType.ATTACHMENT), true); + DocumentResourceReference linkReference = new DocumentResourceReference("reference"); + LinkBlock lb = new LinkBlock(Arrays.asList((Block) new WordBlock("label")), linkReference, false); + Block rootBlock = new ParagraphBlock(Arrays.asList(wb, ib, lb)); + + Block newRootBlock = rootBlock.clone(); + + Assert.assertNotSame(rootBlock, newRootBlock); + Assert.assertNotSame(wb, newRootBlock.getChildren().get(0)); + Assert.assertNotSame(ib, newRootBlock.getChildren().get(1)); + Assert.assertNotSame(lb, newRootBlock.getChildren().get(2)); + + Assert.assertEquals(wb.getWord(), ((WordBlock) newRootBlock.getChildren().get(0)).getWord()); + Assert.assertNotSame(ib.getReference(), ((ImageBlock) newRootBlock.getChildren().get(1)).getReference()); + Assert.assertNotSame(lb.getReference(), ((LinkBlock) newRootBlock.getChildren().get(2)).getReference()); + } + + @Test + public void testGetPreviousBlockByType() { + WordBlock lw = new WordBlock("linkword"); + SpecialSymbolBlock ls = new SpecialSymbolBlock('$'); + + DocumentResourceReference linkReference = new DocumentResourceReference("reference"); + LinkBlock pl = new LinkBlock(Arrays.asList(lw, ls), linkReference, false); + + ImageBlock pi = new ImageBlock(new ResourceReference("document@attachment", ResourceType.ATTACHMENT), true); + + ParagraphBlock rootBlock = new ParagraphBlock(Arrays.asList(pi, pl)); + + Assert.assertSame(lw, ls.getPreviousBlockByType(WordBlock.class, false)); + Assert.assertNull(ls.getPreviousBlockByType(ImageBlock.class, false)); + Assert.assertSame(pl, ls.getPreviousBlockByType(LinkBlock.class, true)); + Assert.assertSame(pi, ls.getPreviousBlockByType(ImageBlock.class, true)); + Assert.assertSame(rootBlock, ls.getPreviousBlockByType(ParagraphBlock.class, true)); + } + + @Test + public void testGetNextSibling() { + WordBlock b1 = new WordBlock("b1"); + WordBlock b2 = new WordBlock("b2"); + ParagraphBlock p = new ParagraphBlock(Arrays.asList(b1, b2)); + + Assert.assertSame(b2, b1.getNextSibling()); + Assert.assertNull(b2.getNextSibling()); + Assert.assertNull(p.getNextSibling()); + Assert.assertNull(new ParagraphBlock(Collections.emptyList()).getNextSibling()); + } + + @Test + public void testRemoveBlock() { + WordBlock b1 = new WordBlock("b1"); + WordBlock b2 = new WordBlock("b2"); + ParagraphBlock p1 = new ParagraphBlock(Arrays.asList(b1, b2)); + + p1.removeBlock(b1); + Assert.assertEquals(1, p1.getChildren().size()); + Assert.assertSame(b2, p1.getChildren().get(0)); + Assert.assertNull(b1.getPreviousSibling()); + Assert.assertNull(b1.getNextSibling()); + Assert.assertNull(b2.getPreviousSibling()); + + p1.removeBlock(b2); + Assert.assertEquals(0, p1.getChildren().size()); + Assert.assertNull(b2.getPreviousSibling()); + Assert.assertNull(b2.getNextSibling()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/block/ProtectedBlockFilterTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/block/ProtectedBlockFilterTest.java new file mode 100644 index 000000000..6d94ed020 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/block/ProtectedBlockFilterTest.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.internal.block; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.Assert; +import org.junit.Test; +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.MacroMarkerBlock; +import org.xwiki.rendering.block.ParagraphBlock; +import org.xwiki.rendering.block.XDOM; + +/** + * Unit tests for {@link org.xwiki.rendering.internal.block.ProtectedBlockFilter}. + * + * @version $Id$ + * @since 2.6 + */ +public class ProtectedBlockFilterTest { + + @Test + public void testGetNextSibling() { + ProtectedBlockFilter pbf = new ProtectedBlockFilter(); + Block b1 = new ParagraphBlock(Collections.emptyList()); + Block b2 = new MacroMarkerBlock("code", Collections.emptyMap(), + Collections.emptyList(), false); + Block b3 = new ParagraphBlock(Collections.emptyList()); + XDOM xdom = new XDOM(Arrays.asList(b1, b2, b3)); + Assert.assertEquals(b3, pbf.getNextSibling(b1)); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/AbstractImageReferenceParserTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/AbstractImageReferenceParserTest.java new file mode 100644 index 000000000..3d19c3816 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/AbstractImageReferenceParserTest.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 org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; +import org.xwiki.rendering.parser.ResourceReferenceParser; + +import com.celements.common.test.AbstractComponentTest; + +/** + * Common tests for Image implementations of + * {@link org.xwiki.rendering.parser.ResourceReferenceParser} for XWiki Syntax + * 2.0 and 2.1. + * + * @version $Id$ + * @since 2.5RC1 + */ +public abstract class AbstractImageReferenceParserTest extends AbstractComponentTest { + + protected ResourceReferenceParser parser; + + protected void registerComponents() throws Exception {} + + @Before + public void prepare() throws Exception { + registerComponents(); + } + + @Test + public void testParseImagesCommon() throws Exception { + // Verify that non-typed image referencing an attachment works. + ResourceReference reference = parser.parse("wiki:space.page@filename"); + Assert.assertEquals(ResourceType.ATTACHMENT, reference.getType()); + Assert.assertEquals("wiki:space.page@filename", reference.getReference()); + Assert.assertEquals("Typed = [false] Type = [attach] Reference = [wiki:space.page@filename]", + reference.toString()); + Assert.assertFalse(reference.isTyped()); + + // Verify that non-typed image referencing a URL works. + reference = parser.parse("http://server/path/to/image"); + Assert.assertEquals(ResourceType.URL, reference.getType()); + Assert.assertEquals("http://server/path/to/image", reference.getReference()); + Assert.assertEquals("Typed = [false] Type = [url] Reference = [http://server/path/to/image]", + reference.toString()); + Assert.assertFalse(reference.isTyped()); + + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/AbstractLinkReferenceParserTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/AbstractLinkReferenceParserTest.java new file mode 100644 index 000000000..f2066352d --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/AbstractLinkReferenceParserTest.java @@ -0,0 +1,95 @@ +/* + * 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.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; +import org.xwiki.rendering.parser.ResourceReferenceParser; + +import com.celements.common.test.AbstractComponentTest; + +/** + * Common tests for Link implementations of + * {@link org.xwiki.rendering.parser.ResourceReferenceParser} for XWiki Syntax + * 2.0 and 2.1. + * + * @version $Id$ + * @since 2.5RC1 + */ +public abstract class AbstractLinkReferenceParserTest extends AbstractComponentTest { + + protected ResourceReferenceParser parser; + + protected void registerComponents() throws Exception {} + + @Before + public void prepare() throws Exception { + registerComponents(); + } + + @Test + public void testParseLinksWhenInWikiModeCommon() throws Exception { + ResourceReference reference = parser.parse(""); + Assert.assertEquals("", reference.getReference()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = []", reference.toString()); + + reference = parser.parse("Hello World"); + Assert.assertEquals("Hello World", reference.getReference()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [Hello World]", reference.toString()); + + reference = parser.parse("http://xwiki.org"); + Assert.assertEquals("http://xwiki.org", reference.getReference()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.URL, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [url] Reference = [http://xwiki.org]", reference.toString()); + + // Verify mailto: URI is recognized + reference = parser.parse("mailto:john@smith.com?subject=test"); + Assert.assertEquals("john@smith.com?subject=test", reference.getReference()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals(ResourceType.MAILTO, reference.getType()); + Assert.assertEquals("Typed = [true] Type = [mailto] Reference = [john@smith.com?subject=test]", + reference.toString()); + + // Verify attach: URI is recognized + reference = parser.parse("attach:some:content"); + Assert.assertEquals("some:content", reference.getReference()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals(ResourceType.ATTACHMENT, reference.getType()); + Assert.assertEquals("Typed = [true] Type = [attach] Reference = [some:content]", reference.toString()); + + // Verify that unknown URIs are ignored + // Note: In this example we point to a document and we consider that myxwiki is the wiki name + // and + // http://xwiki.org is the page name + reference = parser.parse("mywiki:http://xwiki.org"); + Assert.assertEquals("mywiki:http://xwiki.org", reference.getReference()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [mywiki:http://xwiki.org]", reference.toString()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/DefaultImageReferenceParserTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/DefaultImageReferenceParserTest.java new file mode 100644 index 000000000..4e81d31f3 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/DefaultImageReferenceParserTest.java @@ -0,0 +1,67 @@ +/* + * 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.junit.Assert; +import org.junit.Test; +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; + +/** + * Unit tests for {@link DefaultImageReferenceParser}. + * + * @version $Id$ + * @since 2.6M1 + */ +public class DefaultImageReferenceParserTest extends AbstractImageReferenceParserTest { + + @Override + protected void registerComponents() throws Exception { + // Create a Mock WikiModel implementation so that the link parser works in wiki mode + registerComponentMock(WikiModel.class); + this.parser = getComponentManager().lookup(ResourceReferenceParser.class, "image"); + } + + @Test + public void testParseImages() throws Exception { + ResourceReference reference = parser.parse("attach:wiki:space.page@filename"); + Assert.assertEquals(ResourceType.ATTACHMENT, reference.getType()); + Assert.assertEquals("wiki:space.page@filename", reference.getReference()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals("Typed = [true] Type = [attach] Reference = [wiki:space.page@filename]", + reference.toString()); + + // Verify path: support + reference = parser.parse("path:/some/image"); + Assert.assertEquals(ResourceType.PATH, reference.getType()); + Assert.assertEquals("/some/image", reference.getReference()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals("Typed = [true] Type = [path] Reference = [/some/image]", reference.toString()); + + // Verify icon: support + reference = parser.parse("icon:name"); + Assert.assertEquals(ResourceType.ICON, reference.getType()); + Assert.assertEquals("name", reference.getReference()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals("Typed = [true] Type = [icon] Reference = [name]", reference.toString()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/DefaultLinkReferenceParserTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/DefaultLinkReferenceParserTest.java new file mode 100644 index 000000000..8100b4145 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/DefaultLinkReferenceParserTest.java @@ -0,0 +1,117 @@ +/* + * 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.junit.Assert; +import org.junit.Test; +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; + +/** + * Unit tests for {@link DefaultLinkReferenceParser}. + * + * @version $Id$ + * @since 2.6M1 + */ +public class DefaultLinkReferenceParserTest extends AbstractLinkReferenceParserTest { + + @Override + protected void registerComponents() throws Exception { + // Create a Mock WikiModel implementation so that the link parser works in wiki mode + this.parser = getComponentManager().lookup(ResourceReferenceParser.class, "link"); + } + + @Test + public void testParseLinks() throws Exception { + ResourceReference reference = parser.parse("doc:wiki:space.page"); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("wiki:space.page", reference.getReference()); + Assert.assertEquals("Typed = [true] Type = [doc] Reference = [wiki:space.page]", reference.toString()); + Assert.assertTrue(reference.isTyped()); + + // Verify InterWiki links work + reference = parser.parse("interwiki:alias:content"); + Assert.assertEquals(ResourceType.INTERWIKI, reference.getType()); + Assert.assertEquals("content", reference.getReference()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals("alias", ((InterWikiResourceReference) reference).getInterWikiAlias()); + Assert.assertEquals("Typed = [true] Type = [interwiki] Reference = [content] " + + "Parameters = [[interWikiAlias] = [alias]]", reference.toString()); + + // Verify that an invalid InterWiki link is considered as Document link + reference = parser.parse("interwiki:invalid_since_doesnt_have_colon"); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("interwiki:invalid_since_doesnt_have_colon", reference.getReference()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [interwiki:invalid_since_doesnt_have_colon]", + reference.toString()); + + // Verify typed URLs + reference = parser.parse("url:http://xwiki.org"); + Assert.assertEquals(ResourceType.URL, reference.getType()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals("http://xwiki.org", reference.getReference()); + Assert.assertEquals("Typed = [true] Type = [url] Reference = [http://xwiki.org]", reference.toString()); + + // Verify query string and anchors have no meaning in link reference to documents. + reference = parser.parse("Hello World?no=queryString#notAnAnchor"); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Hello World?no=queryString#notAnAnchor", reference.getReference()); + Assert.assertFalse(reference.isTyped()); + Assert.assertNull(((DocumentResourceReference) reference).getAnchor()); + Assert.assertNull(((DocumentResourceReference) reference).getQueryString()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [Hello World?no=queryString#notAnAnchor]", + reference.toString()); + + // Verify that the interwiki separator from XWiki Syntax 2.0 has not meaning in link references + // to documents + reference = parser.parse("page@alias"); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals("page@alias", reference.getReference()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [page@alias]", reference.toString()); + + // Verify path link types + reference = parser.parse("path:/some/path"); + Assert.assertEquals(ResourceType.PATH, reference.getType()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals("/some/path", reference.getReference()); + Assert.assertEquals("Typed = [true] Type = [path] Reference = [/some/path]", reference.toString()); + + // Verify UNC link types + reference = parser.parse("unc:\\\\myserver\\myshare\\mydoc.txt"); + Assert.assertEquals(ResourceType.UNC, reference.getType()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals("\\\\myserver\\myshare\\mydoc.txt", reference.getReference()); + Assert.assertEquals("Typed = [true] Type = [unc] Reference = [\\\\myserver\\myshare\\mydoc.txt]", + reference.toString()); + } + + @Test + public void testParseLinksWithEscapes() throws Exception { + // Veirfy that reference escapes are left as is by the link parser + ResourceReference resourceReference = parser.parse("pa\\.ge"); + Assert.assertEquals(ResourceType.DOCUMENT, resourceReference.getType()); + Assert.assertEquals("pa\\.ge", resourceReference.getReference()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/XWiki20ImageReferenceParserTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/XWiki20ImageReferenceParserTest.java new file mode 100644 index 000000000..ca615784a --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/XWiki20ImageReferenceParserTest.java @@ -0,0 +1,54 @@ +/* + * 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.junit.Assert; +import org.junit.Test; +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; + +/** + * Unit tests for {@link XWiki20ImageReferenceParser}. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class XWiki20ImageReferenceParserTest extends AbstractImageReferenceParserTest { + + @Override + protected void registerComponents() throws Exception { + // Create a Mock WikiModel implementation so that the link parser works in wiki mode + registerComponentMock(WikiModel.class); + this.parser = getComponentManager().lookup(ResourceReferenceParser.class, "xwiki/2.0/image"); + } + + @Test + public void testParseImages() throws Exception { + // Verify that "attach:" prefix isn't taken into account in XWiki Syntax 2.0. + ResourceReference reference = parser.parse("attach:wiki:space.page@filename"); + Assert.assertEquals(ResourceType.ATTACHMENT, reference.getType()); + Assert.assertEquals("attach:wiki:space.page@filename", reference.getReference()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals("Typed = [false] Type = [attach] Reference = [attach:wiki:space.page@filename]", + reference.toString()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/XWiki20LinkReferenceParserTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/XWiki20LinkReferenceParserTest.java new file mode 100644 index 000000000..16d7c027d --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/parser/reference/XWiki20LinkReferenceParserTest.java @@ -0,0 +1,134 @@ +/* + * 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.junit.Assert; +import org.junit.Test; +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.wiki.WikiModel; + +/** + * Unit tests for {@link XWiki20LinkReferenceParser}. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class XWiki20LinkReferenceParserTest extends AbstractLinkReferenceParserTest { + + @Override + protected void registerComponents() throws Exception { + // Create a Mock WikiModel implementation so that the link parser works in wiki mode + registerComponentMock(WikiModel.class); + this.parser = getComponentManager().lookup(ResourceReferenceParser.class, "xwiki/2.0/link"); + } + + @Test + public void testParseLinksWhenInWikiMode() throws Exception { + // Test Query Strings in links to document + ResourceReference reference = parser.parse("Hello World?xredirect=../whatever"); + Assert.assertEquals("Hello World", reference.getReference()); + Assert.assertEquals("xredirect=../whatever", ((DocumentResourceReference) reference).getQueryString()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [Hello World] " + + "Parameters = [[queryString] = [xredirect=../whatever]]", reference.toString()); + + reference = parser.parse("HelloWorld?xredirect=http://xwiki.org"); + Assert.assertEquals("HelloWorld", reference.getReference()); + Assert.assertEquals("xredirect=http://xwiki.org", ((DocumentResourceReference) reference).getQueryString()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [HelloWorld] " + + "Parameters = [[queryString] = [xredirect=http://xwiki.org]]", reference.toString()); + + // Test Anchors in links to documents + reference = parser.parse("#anchor"); + Assert.assertEquals("anchor", ((DocumentResourceReference) reference).getAnchor()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [] Parameters = [[anchor] = [anchor]]", + reference.toString()); + + reference = parser.parse("Hello#anchor"); + Assert.assertEquals("Hello", reference.getReference()); + Assert.assertEquals("anchor", ((DocumentResourceReference) reference).getAnchor()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [Hello] Parameters = [[anchor] = [anchor]]", + reference.toString()); + + // Test InterWiki links + reference = parser.parse("HelloWorld#anchor?param1=1¶m2=2@wikipedia"); + Assert.assertEquals("HelloWorld#anchor?param1=1¶m2=2", reference.getReference()); + Assert.assertEquals("wikipedia", ((InterWikiResourceReference) reference).getInterWikiAlias()); + Assert.assertTrue(reference.isTyped()); + Assert.assertEquals(ResourceType.INTERWIKI, reference.getType()); + Assert.assertEquals("Typed = [true] Type = [interwiki] Reference = [HelloWorld#anchor?param1=1¶m2=2] " + + "Parameters = [[interWikiAlias] = [wikipedia]]", reference.toString()); + + // Verify in XWiki Syntax 2.0 the "doc" prefix is not meaningful + reference = parser.parse("doc:whatever"); + Assert.assertEquals("doc:whatever", reference.getReference()); + Assert.assertFalse(reference.isTyped()); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("Typed = [false] Type = [doc] Reference = [doc:whatever]", reference.toString()); + } + + @Test + public void testParseLinksWithEscapes() throws Exception { + ResourceReference reference = parser.parse("\\.\\#notanchor"); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("\\.#notanchor", reference.getReference()); + Assert.assertNull(((DocumentResourceReference) reference).getAnchor()); + + reference = parser.parse("page\\?notquerystring"); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("page?notquerystring", reference.getReference()); + Assert.assertNull(((DocumentResourceReference) reference).getQueryString()); + + // Verify that \ can be escaped and that escaped chars in query string, and anchors are escaped + reference = parser.parse("page\\\\#anchor\\\\?querystring\\\\"); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("page\\\\", reference.getReference()); + Assert.assertEquals("anchor\\", ((DocumentResourceReference) reference).getAnchor()); + Assert.assertEquals("querystring\\", ((DocumentResourceReference) reference).getQueryString()); + + reference = parser.parse("pa\\.ge\\?query\\#anchor\\@notinterwiki"); + Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); + Assert.assertEquals("pa\\.ge?query#anchor@notinterwiki", reference.getReference()); + + // Verify that \ can be escaped and that escaped chars in query string, anchors and InterWiki + // aliases are + // escaped. + reference = parser.parse("page\\\\#anchor\\\\?querystring\\\\@alias\\\\"); + Assert.assertEquals(ResourceType.INTERWIKI, reference.getType()); + Assert.assertEquals("page\\#anchor\\?querystring\\", reference.getReference()); + Assert.assertEquals("alias\\", ((InterWikiResourceReference) reference).getInterWikiAlias()); + + reference = parser.parse("something\\\\@inter\\@wikilink"); + Assert.assertEquals(ResourceType.INTERWIKI, reference.getType()); + Assert.assertEquals("something\\", reference.getReference()); + Assert.assertEquals("inter@wikilink", ((InterWikiResourceReference) reference).getInterWikiAlias()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRendererTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRendererTest.java new file mode 100644 index 000000000..2fb226890 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRendererTest.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.plain; + +import java.util.Collections; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.rendering.listener.reference.DocumentResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; +import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter; +import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; + +import com.celements.common.test.AbstractComponentTest; + +/** + * Unit tests for {@link PlainTextChainingRenderer} that cannot easily be performed using the + * Rendering Test framework. + * + * @version $Id$ + * @since 2.1M1 + */ +public class PlainTextChainingRendererTest extends AbstractComponentTest { + + private PlainTextRenderer renderer; + + @Before + public void prepare() throws Exception { + // Force the link label generator to be null + this.renderer = new PlainTextRenderer(); + ReflectionUtils.setFieldValue(this.renderer, "defaultLinkReferenceSerializer", + getComponentManager().lookup(ResourceReferenceSerializer.class, "xwiki/2.1/link")); + this.renderer.initialize(); + } + + @Test + public void testBeginLinkWhenLinkLabelGeneratorIsNull() throws Exception { + DefaultWikiPrinter printer = new DefaultWikiPrinter(); + this.renderer.setPrinter(printer); + + DocumentResourceReference reference = new DocumentResourceReference("reference"); + reference.setAnchor("anchor"); + reference.setQueryString("param=value"); + + this.renderer.beginLink(reference, false, Collections.emptyMap()); + this.renderer.endLink(reference, false, Collections.emptyMap()); + + Assert.assertEquals("reference", printer.toString()); + } + + @Test + public void testBeginLinkWhenExternalLink() throws Exception { + DefaultWikiPrinter printer = new DefaultWikiPrinter(); + this.renderer.setPrinter(printer); + + ResourceReference reference = new ResourceReference("http://some/url", ResourceType.URL); + this.renderer.beginLink(reference, false, Collections.emptyMap()); + this.renderer.endLink(reference, false, Collections.emptyMap()); + + Assert.assertEquals("http://some/url", printer.toString()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManagerTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManagerTest.java new file mode 100644 index 000000000..3ef74c992 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManagerTest.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.transformation; + +import org.junit.Test; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.transformation.TransformationContext; +import org.xwiki.rendering.transformation.TransformationManager; + +import com.celements.common.test.AbstractComponentTest; + +/** + * Unit tests for {@link DefaultTransformationManager}. + * + * @version $Id$ + */ +public class DefaultTransformationManagerTest extends AbstractComponentTest { + + @Test + public void testTransformations() throws Exception { + TransformationManager manager = getComponentManager().lookup(TransformationManager.class); + manager.performTransformations(XDOM.EMPTY, new TransformationContext(XDOM.EMPTY, Syntax.XWIKI_2_0)); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListenerTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListenerTest.java new file mode 100644 index 000000000..05de52114 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListenerTest.java @@ -0,0 +1,96 @@ +/* + * 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.listener.chaining; + +import java.util.Collections; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Unit tests for {@link LookaheadChainingListener}. + * + * @version $Id$ + * @since 2.0M3 + */ +public class EmptyBlockChainingListenerTest { + + private ListenerChain chain; + + private EmptyBlockChainingListener listener; + + @Before + public void setUp() { + chain = new ListenerChain(); + listener = new EmptyBlockChainingListener(chain); + chain.addListener(listener); + } + + /** + * Verify that isCurrentContainerBlockEmpty return true if there's no children inside a paragraph + * container block. + */ + @Test + public void testEmptyParagraphContainer() { + chain.addListener(new AbstractChainingListener() { + + { + setListenerChain(chain); + } + + @Override + public void endParagraph(Map parameters) { + EmptyBlockChainingListener blockState = (EmptyBlockChainingListener) getListenerChain() + .getListener(EmptyBlockChainingListener.class); + Assert.assertTrue(blockState.isCurrentContainerBlockEmpty()); + } + }); + + listener.beginParagraph(Collections.emptyMap()); + listener.endParagraph(Collections.emptyMap()); + } + + /** + * Verify that isCurrentContainerBlockEmpty return false if there are children inside a paragraph + * container block. + */ + @Test + public void testNonEmptyParagraphContainer() { + chain.addListener(new AbstractChainingListener() { + + { + setListenerChain(chain); + } + + @Override + public void endParagraph(Map parameters) { + EmptyBlockChainingListener blockState = (EmptyBlockChainingListener) getListenerChain() + .getListener(EmptyBlockChainingListener.class); + Assert.assertFalse(blockState.isCurrentContainerBlockEmpty()); + } + }); + + listener.beginParagraph(Collections.emptyMap()); + listener.onWord("word"); + listener.endParagraph(Collections.emptyMap()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListenerTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListenerTest.java new file mode 100644 index 000000000..ec76b163b --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListenerTest.java @@ -0,0 +1,102 @@ +/* + * 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.listener.chaining; + +import java.util.Collections; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit tests for {@link LookaheadChainingListener}. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class LookaheadChainingListenerTest { + + public class TestChainingListener extends AbstractChainingListener { + + public int calls = 0; + + public TestChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + @Override + public void beginDocument(Map parameters) { + this.calls++; + } + + @Override + public void beginParagraph(Map parameters) { + this.calls++; + } + + @Override + public void endDocument(Map parameters) { + this.calls++; + } + + @Override + public void endParagraph(Map parameters) { + this.calls++; + } + } + + @Test + public void testLookahead() { + ListenerChain chain = new ListenerChain(); + LookaheadChainingListener listener = new LookaheadChainingListener(chain, 2); + chain.addListener(listener); + TestChainingListener testListener = new TestChainingListener(chain); + chain.addListener(testListener); + + // The begin document flushes + listener.beginDocument(Collections.emptyMap()); + Assert.assertEquals(1, testListener.calls); + + // 1st lookahead, nothing is sent to the test listener + listener.beginParagraph(Collections.emptyMap()); + Assert.assertEquals(1, testListener.calls); + Assert.assertEquals(EventType.BEGIN_PARAGRAPH, listener.getNextEvent().eventType); + Assert.assertNull(listener.getNextEvent(2)); + + // 2nd lookahead, nothing is sent to the test listener + listener.beginParagraph(Collections.emptyMap()); + Assert.assertEquals(1, testListener.calls); + Assert.assertEquals(EventType.BEGIN_PARAGRAPH, listener.getNextEvent().eventType); + Assert.assertEquals(EventType.BEGIN_PARAGRAPH, listener.getNextEvent(2).eventType); + Assert.assertNull(listener.getNextEvent(3)); + + // 3rd events, the first begin paragraph is sent + listener.endParagraph(Collections.emptyMap()); + Assert.assertEquals(2, testListener.calls); + Assert.assertEquals(EventType.BEGIN_PARAGRAPH, listener.getNextEvent().eventType); + Assert.assertEquals(EventType.END_PARAGRAPH, listener.getNextEvent(2).eventType); + Assert.assertNull(listener.getNextEvent(3)); + + // The end document flushes + listener.endDocument(Collections.emptyMap()); + Assert.assertEquals(5, testListener.calls); + Assert.assertNull(listener.getNextEvent()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/parser/SyntaxTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/parser/SyntaxTest.java new file mode 100644 index 000000000..ccb54dca8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/parser/SyntaxTest.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.parser; + +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.syntax.SyntaxType; + +import junit.framework.TestCase; + +/** + * Unit tests for {@link org.xwiki.rendering.syntax.Syntax}. + * + * @version $Id$ + * @since 1.5M2 + */ +public class SyntaxTest extends TestCase { + + public void testEquality() { + Syntax syntax1 = new Syntax(new SyntaxType("mytype", "My Type"), "1.0"); + Syntax syntax2 = new Syntax(new SyntaxType("mytype", "My Type"), "1.0"); + Syntax syntax3 = new Syntax(new SyntaxType("mytype", "Still same type"), "1.0"); + + assertEquals("mytype", syntax1.getType().getId()); + assertEquals("My Type", syntax1.getType().getName()); + + assertEquals(syntax2, syntax1); + // The syntax type name is not part of the equality test. + assertEquals(syntax3, syntax1); + } + + public void testNonEquality() { + Syntax syntax1 = new Syntax(SyntaxType.XWIKI, "1.0"); + Syntax syntax2 = new Syntax(SyntaxType.XWIKI, "2.0"); + Syntax syntax3 = new Syntax(SyntaxType.CONFLUENCE, "1.0"); + + assertFalse(syntax2.equals(syntax1)); + assertFalse(syntax3.equals(syntax1)); + } + + public void testToString() { + Syntax syntax = new Syntax(SyntaxType.XWIKI, "1.0"); + assertEquals("XWiki 1.0", syntax.toString()); + assertEquals("xwiki/1.0", syntax.toIdString()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/scaffolding/BlockAssert.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/scaffolding/BlockAssert.java new file mode 100644 index 000000000..e1eadd393 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/scaffolding/BlockAssert.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.scaffolding; + +import java.util.List; + +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.renderer.PrintRenderer; +import org.xwiki.rendering.renderer.PrintRendererFactory; +import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * Class to be imported in unit tests as a static import and which contains helper methods to assert + * Rendering Blocks. + * + * @version $Id$ + * @since 2.4M2 + */ +public class BlockAssert { + + /** + * Protect constructor since it is a static only class + */ + protected BlockAssert() { + // Nothing to do + } + + public static void assertBlocks(String expected, List blocks, PrintRendererFactory factory) + throws Exception { + // Assert the result by parsing it through the EventsRenderer to generate easily + // assertable events. + XDOM dom = new XDOM(blocks); + WikiPrinter printer = new DefaultWikiPrinter(); + + PrintRenderer eventRenderer = factory.createRenderer(printer); + + dom.traverse(eventRenderer); + junit.framework.Assert.assertEquals(expected, printer.toString()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/util/IdGeneratorTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/util/IdGeneratorTest.java new file mode 100644 index 000000000..8c87fd915 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/util/IdGeneratorTest.java @@ -0,0 +1,82 @@ +package org.xwiki.rendering.util; + +/* + * 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. + */ +import junit.framework.TestCase; + +/** + * Validate {@link IdGenerator}. + * + * @version $Id$ + */ +public class IdGeneratorTest extends TestCase { + + private IdGenerator idGenerator; + + /** + * {@inheritDoc} + * + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + + this.idGenerator = new IdGenerator(); + } + + public void testGenerateUniqueId() { + assertEquals("Itext", this.idGenerator.generateUniqueId("text")); + assertEquals("Itext-1", this.idGenerator.generateUniqueId("te xt")); + } + + public void testGenerateUniqueIdWithPrefix() { + assertEquals("prefixtext", this.idGenerator.generateUniqueId("prefix", "text")); + assertEquals("prefixtext-1", this.idGenerator.generateUniqueId("prefix", "te xt")); + } + + public void testGenerateUniqueIdFromNonAlphaNum() { + assertEquals("I:_.-", this.idGenerator.generateUniqueId(":_.-")); + assertEquals("Iwithspace", this.idGenerator.generateUniqueId("with space")); + assertEquals("Iwithtab", this.idGenerator.generateUniqueId("with\ttab")); + assertEquals("I5BC67801", this.idGenerator.generateUniqueId("\u5BC6\u7801")); + assertEquals("I3D", this.idGenerator.generateUniqueId("=")); + } + + public void testGenerateUniqueIdWhenInvalidEmptyPrefix() { + try { + this.idGenerator.generateUniqueId("", "whatever"); + fail("Should have thrown an exception"); + } catch (IllegalArgumentException expected) { + assertEquals("The prefix [] should only contain alphanumerical characters and not be empty.", + expected.getMessage()); + } + } + + public void testGenerateUniqueIdWhenInvalidNonAlphaPrefix() { + try { + this.idGenerator.generateUniqueId("a-b", "whatever"); + fail("Should have thrown an exception"); + } catch (IllegalArgumentException expected) { + assertEquals("The prefix [a-b] should only contain alphanumerical characters and not be empty.", + expected.getMessage()); + } + } +}