/**
* Copyright 2015-2017 Linagora, Université Joseph Fourier, Floralis
*
* The present code is developed in the scope of the joint LINAGORA -
* Université Joseph Fourier - Floralis research program and is designated
* as a "Result" pursuant to the terms and conditions of the LINAGORA
* - Université Joseph Fourier - Floralis research program. Each copyright
* holder of Results enumerated here above fully & independently holds complete
* ownership of the complete Intellectual Property rights applicable to the whole
* of said Results, and may freely exploit it in any manner which does not infringe
* the moral rights of the other copyright holders.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.roboconf.doc.generator.internal.renderers;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import net.roboconf.core.model.beans.ApplicationTemplate;
import net.roboconf.core.utils.Utils;
import net.roboconf.doc.generator.DocConstants;
import net.roboconf.doc.generator.internal.AbstractStructuredRenderer;
/**
* A renderer that outputs Fop.
* @author Amadou Diarra - UGA
*/
public class FopRenderer extends AbstractStructuredRenderer {
private static final String TITLE_MARKUP = "${TITLE}";
private static final String CONTENT_MARKUP = "${CONTENT}";
/**
* Constructor.
* @param outputDirectory
* @param applicationTemplate
* @param applicationDirectory
* @param typeAnnotations
*/
public FopRenderer(
File outputDirectory,
ApplicationTemplate applicationTemplate,
File applicationDirectory,
Map<String,String> typeAnnotations ) {
super( outputDirectory, applicationTemplate, applicationDirectory, typeAnnotations );
}
@Override
protected String renderTitle1(String title) {
return "<fo:block font-size=\"18pt\" font-weight=\"bold\">" + title + "</fo:block>\n";
}
@Override
protected String renderTitle2(String title) {
return "<fo:block font-size=\"14pt\" font-weight=\"bold\">" + title + "</fo:block>\n";
}
@Override
protected String renderTitle3(String title) {
return "<fo:block font-size=\"12pt\" font-weight=\"bold\">" + title + "</fo:block>\n";
}
@Override
protected String renderParagraph(String paragraph) {
StringBuilder sb = new StringBuilder();
for( String s : paragraph.trim().split( "\n\n" )) {
sb.append( "\n<fo:block>" );
sb.append( s.trim().replaceAll( "\n", "<br />" ));
sb.append( "</fo:block>\n\n" );
}
return sb.toString();
}
@Override
protected String renderList(Collection<String> listItems) {
StringBuilder sb = new StringBuilder();
sb.append( "\n<fo:list-block provisional-label-separation=\"2pt\"" );
sb.append( " provisional-distance-between-starts=\"8pt\">\n" );
for( String s : listItems ) {
sb.append( "\t<fo:list-item>\n" );
sb.append( "\t\t<fo:list-item-label end-indent=\"label-end()\">\n" );
sb.append( "\t\t <fo:block> - </fo:block>\n" );
sb.append( "\t\t</fo:list-item-label>\n" );
sb.append( "\t\t<fo:list-item-body start-indent=\"body-start()\">\n" );
sb.append( "\t\t <fo:block>" );
sb.append( s );
sb.append( "</fo:block>\n" );
sb.append( "\t\t</fo:list-item-body>\n" );
sb.append( "\t</fo:list-item>\n");
}
sb.append( "</fo:list-block>\n" );
return sb.toString();
}
@Override
protected String renderPageBreak() {
return "<fo:block break-after=\"page\"/>";
}
@Override
protected String indent() {
return "\t";
}
@Override
protected String startTable() {
return "\n<fo:table text-align=\"center\" space-before=\"1em\" table-layout=\"fixed\" border=\"0.5pt solid black\">\n";
}
@Override
protected String endTable() {
return "</fo:table>\n";
}
@Override
protected String addTableHeader(String... headerEntries) {
StringBuilder sb = new StringBuilder();
sb.append( "<fo:table-body>\n" );
sb.append( "\t<fo:table-row>\n" );
for( String s : headerEntries ) {
sb.append( "\t <fo:table-cell border=\"0.5pt solid black\">" );
sb.append( "<fo:block>" );
sb.append( s );
sb.append( "</fo:block>" );
sb.append( "</fo:table-cell>\n" );
}
sb.append( "\t</fo:table-row>\n" );
sb.append( "</fo:table-body>\n" );
return sb.toString();
}
@Override
protected String addTableLine(String... lineEntries) {
StringBuilder sb = new StringBuilder();
sb.append( "\t<fo:table-body>\n" );
sb.append( "\t\t<fo:table-row>\n" );
for( String s : lineEntries ) {
sb.append( "\t\t <fo:table-cell border=\"0.5pt solid black\" padding=\"2pt 5pt\">" );
sb.append( "<fo:block>" );
sb.append( s );
sb.append( "</fo:block>" );
sb.append( "\n</fo:table-cell>" );
}
sb.append( "\n\t\t</fo:table-row>\n" );
sb.append( "\t</fo:table-body>\n" );
return sb.toString();
}
@Override
protected String renderDocumentTitle() {
return "<fo:block font-size=\"18pt\" font-weight=\"bold\">" + this.applicationTemplate.getName() + "</fo:block>\n";
}
@Override
protected String renderDocumentIndex() {
// What keys should we inject in the index?
List<String> keys = new ArrayList<> ();
keys.add( "introduction" );
keys.add( "components" );
if( this.options.containsKey( DocConstants.OPTION_RECIPE ) ) {
if( ! this.applicationTemplate.getGraphs().getFacetNameToFacet().isEmpty() )
keys.add( "facets" );
} else {
keys.add( "instances" );
}
// Create the index
StringBuilder sb = new StringBuilder();
sb.append( "\n<fo:list-block provisional-label-separation=\"2pt\"" );
sb.append( " provisional-distance-between-starts=\"8pt\">\n" );
for( String key : keys ) {
sb.append( "\t<fo:list-item>\n" );
sb.append( "\t\t<fo:list-item-label end-indent=\"label-end()\">\n" );
sb.append( "\t\t <fo:block> - </fo:block>\n" );
sb.append( "\t\t</fo:list-item-label>\n" );
sb.append( "\t\t<fo:list-item-body start-indent=\"body-start()\">\n" );
sb.append( "\t\t <fo:block>" );
sb.append( this.messages.get( key ));
sb.append( "</fo:block>\n" );
sb.append( "\t\t</fo:list-item-body>\n" );
sb.append( "\t</fo:list-item>\n");
}
sb.append( "</fo:list-block>\n" );
return sb.toString();
}
@Override
protected String renderImage(String componentName, DiagramType type, String relativeImagePath) {
StringBuilder sb = new StringBuilder();
sb.append( "<fo:block>\n" );
sb.append( "\t<fo:external-graphic src=\"" + relativeImagePath + "\" />\n" );
sb.append( "</fo:block>" );
return sb.toString();
}
@Override
protected String applyBoldStyle(String text, String keyword) {
return text.replaceAll( Pattern.quote( keyword ), "<fo:block font-weight=\"bold\">" + keyword + "</fo:block>" );
}
@Override
protected String applyLink(String text, String linkId) {
return text.replaceAll( Pattern.quote( text ), "<fo:basic-link external-destination=\"" + "url(" + createId( linkId ) + ")" +"\">" + text + "</fo:basic-link>" );
}
@Override
protected File writeFileContent(String fileContent) throws IOException {
// Load the template
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = getClass().getResourceAsStream( "/fop.tpl" );
Utils.copyStreamSafely( in, out );
//Copy the header in outputDirectory
InputStream h = getClass().getResourceAsStream( "/roboconf.jpg" );
File imgFile = new File( this.outputDirectory, "header.jpg" );
Utils.copyStream( h, imgFile );
// Create the target directory
File targetFile = new File( this.outputDirectory, "index.fo" );
Utils.createDirectory( targetFile.getParentFile());
// Write the main file
String toWrite = out.toString( "UTF-8" )
.replace( TITLE_MARKUP, this.applicationTemplate.getName())
.replace( CONTENT_MARKUP, fileContent )
.replace( "header.jpg", this.outputDirectory.getAbsolutePath() + "/header.jpg" )
.replace( "png/", this.outputDirectory.getAbsolutePath() + "/png/" )
.replaceAll( "\n{3,}", "\n\n" );
Utils.writeStringInto( toWrite, targetFile );
return targetFile;
}
@Override
protected StringBuilder endSection(String sectionName, StringBuilder sb) {
StringBuilder result = sb;
return result;
}
@Override
protected String renderSections(List<String> sectionNames) {
return "";
}
@Override
protected StringBuilder startSection(String sectionName) {
return new StringBuilder();
}
private String createId( String title ) {
return title.toLowerCase().replaceAll( "\\s+", "-" );
}
}