/* * Copyright (C) 2003-2010 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.wiki.rendering.render.confluence; 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.listener.QueueListener.Event; import org.xwiki.rendering.listener.chaining.EventType; import org.xwiki.rendering.listener.reference.ResourceReference; import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; /** * Created by The eXo Platform SAS * Author : viet nguyen * viet.nguyen@exoplatform.com * Jul 2, 2010 */ /** * Logic to render a Confluence Link into Confluence syntax. */ public class ConfluenceSyntaxLinkRenderer { private ParametersPrinter parametersPrinter = new ParametersPrinter(); private Stack<Boolean> forceFullSyntax = new Stack<Boolean>(); private ConfluenceSyntaxListenerChain listenerChain; private ResourceReferenceSerializer linkReferenceSerializer; public ConfluenceSyntaxLinkRenderer(ConfluenceSyntaxListenerChain listenerChain, ResourceReferenceSerializer linkReferenceSerializer) { this.listenerChain = listenerChain; this.linkReferenceSerializer = linkReferenceSerializer; this.forceFullSyntax.push(false); } /** * {@inheritDoc} * * @see DefaultLinkReferenceSerializer#serialize(org.xwiki.rendering.listener.Link) */ public String serialize(ResourceReference link) { return this.linkReferenceSerializer.serialize(link); } public void beginRenderLink(ConfluenceSyntaxEscapeWikiPrinter printer, ResourceReference link, boolean isFreeStandingURI, Map<String, String> 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(ConfluenceSyntaxEscapeWikiPrinter printer, boolean isFreeStandingURI, Map<String, String> parameters) { return forceFullSyntax(printer, true, isFreeStandingURI, parameters); } public boolean forceFullSyntax(ConfluenceSyntaxEscapeWikiPrinter printer, boolean isLastSyntax, boolean isFreeStandingURI, Map<String, String> 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 ConfluenceSyntaxLinkRenderer) 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(ConfluenceSyntaxEscapeWikiPrinter 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(ConfluenceSyntaxEscapeWikiPrinter printer, ResourceReference link, boolean isFreeStandingURI, Map<String, String> parameters) { printer.print(serialize(link)); // If there were parameters specified, output them separated by the "|" characters if (!parameters.isEmpty()) { printer.print("|"); printer.print(this.parametersPrinter.print(parameters, '~')); } if (this.forceFullSyntax.peek() || !isFreeStandingURI) { printer.print("]"); } this.forceFullSyntax.pop(); } }