001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.render; 020 021import org.apache.wiki.api.core.Context; 022import org.apache.wiki.parser.PluginContent; 023import org.apache.wiki.parser.WikiDocument; 024import org.jdom2.Content; 025import org.jdom2.Element; 026import org.jdom2.Text; 027 028import java.util.ArrayList; 029import java.util.List; 030 031/** 032 * Implements DOM-to-Creole rendering. 033 * <p> 034 * FIXME: This class is not yet completely done. 035 * 036 */ 037public class CreoleRenderer extends WikiRenderer { 038 039 private static final String IMG_START = "{{"; 040 private static final String IMG_END = "}}"; 041 private static final String PLUGIN_START = "<<"; 042 private static final String PLUGIN_END = ">>"; 043 private static final String HREF_START = "[["; 044 private static final String HREF_DELIMITER = "|"; 045 private static final String HREF_END = "]]"; 046 private static final String PRE_START = "{{{"; 047 private static final String PRE_END = "}}}"; 048 private static final String PLUGIN_IMAGE = "Image"; 049 private static final String PARAM_SRC = "src"; 050 private static final String HREF_ATTRIBUTE = "href"; 051 private static final String ONE_SPACE = " "; 052 private static final String EMPTY_STRING = ""; 053 private static final String LINEBREAK = "\n"; 054 private static final String LI = "li"; 055 private static final String UL = "ul"; 056 private static final String OL = "ol"; 057 private static final String P = "p"; 058 private static final String A = "a"; 059 private static final String PRE = "pre"; 060 061 /** 062 * Contains element, start markup, end markup 063 */ 064 private static final String[] ELEMENTS = { 065 "i" , "//" , "//", 066 "b" , "**" , "**", 067 "h2", "== " , " ==", 068 "h3", "=== " , " ===", 069 "h4", "==== " , " ====", 070 "hr", "----" , EMPTY_STRING, 071 "tt", "<<{{>>", "<<}}>>" 072 }; 073 074 private int m_listCount; 075 private char m_listChar = 'x'; 076 077 private final List< PluginContent > m_plugins = new ArrayList<>(); 078 079 /** 080 * Creates a new Creole Renderer. 081 */ 082 public CreoleRenderer( final Context ctx, final WikiDocument doc ) 083 { 084 super( ctx, doc ); 085 } 086 087 /** 088 * Renders an element into the StringBuilder given 089 * @param ce element to render 090 * @param sb stringbuilder holding the element render 091 */ 092 private void renderElement( final Element ce, final StringBuilder sb ) { 093 String endEl = EMPTY_STRING; 094 for( int i = 0; i < ELEMENTS.length; i+=3 ) { 095 if( ELEMENTS[i].equals(ce.getName()) ) { 096 sb.append( ELEMENTS[i+1] ); 097 endEl = ELEMENTS[i+2]; 098 } 099 } 100 101 if( UL.equals(ce.getName()) ) { 102 m_listCount++; 103 m_listChar = '*'; 104 } else if( OL.equals(ce.getName()) ) { 105 m_listCount++; 106 m_listChar = '#'; 107 } else if( LI.equals(ce.getName()) ) { 108 for(int i = 0; i < m_listCount; i++ ) sb.append( m_listChar ); 109 sb.append( ONE_SPACE ); 110 } else if( A.equals( ce.getName() ) ) { 111 final String href = ce.getAttributeValue( HREF_ATTRIBUTE ); 112 final String text = ce.getText(); 113 114 if( href.equals( text ) ) { 115 sb.append( HREF_START ).append( href ).append( HREF_END ); 116 } else { 117 sb.append( HREF_START ).append( href ).append( HREF_DELIMITER ).append( text ).append( HREF_END); 118 } 119 // Do not render anything else 120 return; 121 } else if( PRE.equals( ce.getName() ) ) { 122 sb.append( PRE_START ); 123 sb.append( ce.getText() ); 124 sb.append( PRE_END ); 125 126 return; 127 } 128 129 // Go through the children 130 for( final Content c : ce.getContent() ) { 131 if( c instanceof PluginContent ) { 132 final PluginContent pc = ( PluginContent )c; 133 134 if( pc.getPluginName().equals( PLUGIN_IMAGE ) ) { 135 sb.append( IMG_START ).append( pc.getParameter( PARAM_SRC ) ).append( IMG_END ); 136 } else { 137 m_plugins.add(pc); 138 sb.append( PLUGIN_START ).append( pc.getPluginName() ).append( ONE_SPACE ).append( m_plugins.size() ).append( PLUGIN_END ); 139 } 140 } else if( c instanceof Text ) { 141 sb.append( ( ( Text )c ).getText() ); 142 } else if( c instanceof Element ) { 143 renderElement( ( Element )c, sb ); 144 } 145 } 146 147 if( UL.equals( ce.getName() ) || OL.equals( ce.getName() ) ) { 148 m_listCount--; 149 } else if( P.equals( ce.getName() ) ) { 150 sb.append( LINEBREAK ); 151 } 152 153 sb.append(endEl); 154 } 155 156 /** 157 * {@inheritDoc} 158 */ 159 public String getString() { 160 final StringBuilder sb = new StringBuilder(1000); 161 final Element ce = m_document.getRootElement(); 162 163 // Traverse through the entire tree of everything. 164 renderElement( ce, sb ); 165 return sb.toString(); 166 } 167 168}