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 java.io.IOException; 022import java.util.ArrayList; 023import java.util.Iterator; 024import java.util.List; 025 026import org.apache.wiki.WikiContext; 027import org.apache.wiki.parser.PluginContent; 028import org.apache.wiki.parser.WikiDocument; 029import org.jdom2.Content; 030import org.jdom2.Element; 031import org.jdom2.Text; 032 033/** 034 * Implements DOM-to-Creole rendering. 035 * <p> 036 * FIXME: This class is not yet completely done. 037 * 038 */ 039public class CreoleRenderer extends WikiRenderer 040{ 041 private static final String IMG_START = "{{"; 042 private static final String IMG_END = "}}"; 043 private static final String PLUGIN_START = "<<"; 044 private static final String PLUGIN_END = ">>"; 045 private static final String HREF_START = "[["; 046 private static final String HREF_DELIMITER = "|"; 047 private static final String HREF_END = "]]"; 048 private static final String PRE_START = "{{{"; 049 private static final String PRE_END = "}}}"; 050 private static final String PLUGIN_IMAGE = "Image"; 051 private static final String PARAM_SRC = "src"; 052 private static final String HREF_ATTRIBUTE = "href"; 053 private static final String ONE_SPACE = " "; 054 private static final String EMPTY_STRING = ""; 055 private static final String LINEBREAK = "\n"; 056 private static final String LI = "li"; 057 private static final String UL = "ul"; 058 private static final String OL = "ol"; 059 private static final String P = "p"; 060 private static final String A = "a"; 061 private static final String PRE = "pre"; 062 063 /** 064 * Contains element, start markup, end markup 065 */ 066 private static final String[] ELEMENTS = { 067 "i" , "//" , "//", 068 "b" , "**" , "**", 069 "h2", "== " , " ==", 070 "h3", "=== " , " ===", 071 "h4", "==== " , " ====", 072 "hr", "----" , EMPTY_STRING, 073 "tt", "<<{{>>", "<<}}>>" 074 }; 075 076 private int m_listCount = 0; 077 private char m_listChar = 'x'; 078 079 private List<PluginContent> m_plugins = new ArrayList<PluginContent>(); 080 081 /** 082 * Creates a new Creole Renderer. 083 * 084 */ 085 public CreoleRenderer( WikiContext ctx, WikiDocument doc ) 086 { 087 super( ctx, doc ); 088 } 089 090 /** 091 * Renders an element into the StringBuilder given 092 * @param ce 093 * @param sb 094 */ 095 private void renderElement( Element ce, StringBuilder sb ) 096 { 097 String endEl = EMPTY_STRING; 098 for( int i = 0; i < ELEMENTS.length; i+=3 ) 099 { 100 if( ELEMENTS[i].equals(ce.getName()) ) 101 { 102 sb.append( ELEMENTS[i+1] ); 103 endEl = ELEMENTS[i+2]; 104 } 105 } 106 107 if( UL.equals(ce.getName()) ) 108 { 109 m_listCount++; 110 m_listChar = '*'; 111 } 112 else if( OL.equals(ce.getName()) ) 113 { 114 m_listCount++; 115 m_listChar = '#'; 116 } 117 else if( LI.equals(ce.getName()) ) 118 { 119 for(int i = 0; i < m_listCount; i++ ) sb.append( m_listChar ); 120 sb.append( ONE_SPACE ); 121 } 122 else if( A.equals(ce.getName()) ) 123 { 124 String href = ce.getAttributeValue( HREF_ATTRIBUTE ); 125 String text = ce.getText(); 126 127 if( href.equals(text) ) 128 { 129 sb.append( HREF_START + href + HREF_END ); 130 } 131 else 132 { 133 sb.append( HREF_START + href+ HREF_DELIMITER + text +HREF_END); 134 } 135 // Do not render anything else 136 return; 137 } 138 else if( PRE.equals(ce.getName()) ) 139 { 140 sb.append( PRE_START ); 141 sb.append( ce.getText() ); 142 sb.append( PRE_END ); 143 144 return; 145 } 146 147 // 148 // Go through the children 149 // 150 for( Iterator< Content > i = ce.getContent().iterator(); i.hasNext(); ) 151 { 152 Content c = i.next(); 153 154 if( c instanceof PluginContent ) 155 { 156 PluginContent pc = (PluginContent)c; 157 158 if( pc.getPluginName().equals( PLUGIN_IMAGE ) ) 159 { 160 sb.append( IMG_START + pc.getParameter( PARAM_SRC ) + IMG_END ); 161 } 162 else 163 { 164 m_plugins.add(pc); 165 sb.append( PLUGIN_START + pc.getPluginName() + ONE_SPACE + m_plugins.size() + PLUGIN_END ); 166 } 167 } 168 else if( c instanceof Text ) 169 { 170 sb.append( ((Text)c).getText() ); 171 } 172 else if( c instanceof Element ) 173 { 174 renderElement( (Element)c, sb ); 175 } 176 } 177 178 if( UL.equals( ce.getName() ) || OL.equals( ce.getName() ) ) 179 { 180 m_listCount--; 181 } 182 else if( P.equals( ce.getName() ) ) 183 { 184 sb.append( LINEBREAK ); 185 } 186 187 sb.append(endEl); 188 } 189 190 /** 191 * {@inheritDoc} 192 */ 193 public String getString() throws IOException 194 { 195 StringBuilder sb = new StringBuilder(1000); 196 197 Element ce = m_document.getRootElement(); 198 199 // 200 // Traverse through the entire tree of everything. 201 // 202 203 renderElement( ce, sb ); 204 205 return sb.toString(); 206 } 207 208}