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; 030import java.util.stream.Collectors; 031import java.util.stream.IntStream; 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; 077 private char m_listChar = 'x'; 078 079 private final List< PluginContent > m_plugins = new ArrayList<>(); 080 081 /** 082 * Creates a new Creole Renderer. 083 */ 084 public CreoleRenderer( final Context ctx, final WikiDocument doc ) 085 { 086 super( ctx, doc ); 087 } 088 089 /** 090 * Renders an element into the StringBuilder given 091 * @param ce element to render 092 * @param sb stringbuilder holding the element render 093 */ 094 private void renderElement( final Element ce, final StringBuilder sb ) { 095 String endEl = EMPTY_STRING; 096 for( int i = 0; i < ELEMENTS.length; i+=3 ) { 097 if( ELEMENTS[i].equals(ce.getName()) ) { 098 sb.append( ELEMENTS[i+1] ); 099 endEl = ELEMENTS[i+2]; 100 } 101 } 102 103 if( UL.equals(ce.getName()) ) { 104 m_listCount++; 105 m_listChar = '*'; 106 } else if( OL.equals(ce.getName()) ) { 107 m_listCount++; 108 m_listChar = '#'; 109 } else if( LI.equals(ce.getName()) ) { 110 sb.append(IntStream.range(0, m_listCount).mapToObj(i -> String.valueOf(m_listChar)).collect(Collectors.joining("", "", ONE_SPACE))); 111 } else if( A.equals( ce.getName() ) ) { 112 final String href = ce.getAttributeValue( HREF_ATTRIBUTE ); 113 final String text = ce.getText(); 114 115 if( href.equals( text ) ) { 116 sb.append( HREF_START ).append( href ).append( HREF_END ); 117 } else { 118 sb.append( HREF_START ).append( href ).append( HREF_DELIMITER ).append( text ).append( HREF_END); 119 } 120 // Do not render anything else 121 return; 122 } else if( PRE.equals( ce.getName() ) ) { 123 sb.append( PRE_START ); 124 sb.append( ce.getText() ); 125 sb.append( PRE_END ); 126 127 return; 128 } 129 130 // Go through the children 131 for( final Content c : ce.getContent() ) { 132 if( c instanceof PluginContent ) { 133 final PluginContent pc = ( PluginContent )c; 134 135 if( pc.getPluginName().equals( PLUGIN_IMAGE ) ) { 136 sb.append( IMG_START ).append( pc.getParameter( PARAM_SRC ) ).append( IMG_END ); 137 } else { 138 m_plugins.add(pc); 139 sb.append( PLUGIN_START ).append( pc.getPluginName() ).append( ONE_SPACE ).append( m_plugins.size() ).append( PLUGIN_END ); 140 } 141 } else if( c instanceof Text ) { 142 sb.append( ( ( Text )c ).getText() ); 143 } else if( c instanceof Element ) { 144 renderElement( ( Element )c, sb ); 145 } 146 } 147 148 if( UL.equals( ce.getName() ) || OL.equals( ce.getName() ) ) { 149 m_listCount--; 150 } else if( P.equals( ce.getName() ) ) { 151 sb.append( LINEBREAK ); 152 } 153 154 sb.append(endEl); 155 } 156 157 /** 158 * {@inheritDoc} 159 */ 160 @Override 161 public String getString() { 162 final StringBuilder sb = new StringBuilder(1000); 163 final Element ce = m_document.getRootElement(); 164 165 // Traverse through the entire tree of everything. 166 renderElement( ce, sb ); 167 return sb.toString(); 168 } 169 170}