/*
* Copyright (c) 2012, Fromentin Xavier, Schnell Michaël, Dervin Cyrielle, Brabant Quentin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of its contributors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Fromentin Xavier, Schnell Michaël, Dervin Cyrielle OR Brabant Quentin
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package gword.generateur;
import gword.exception.WordGenerationException;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Hashtable;
import kameleon.document.Array;
import kameleon.document.BulletListElement;
import kameleon.document.Cell;
import kameleon.document.Document;
import kameleon.document.ElementPropertiesDefaultNames;
import kameleon.document.HorizontalSeparator;
import kameleon.document.HyperTextLink;
import kameleon.document.LineBreak;
import kameleon.document.ListElement;
import kameleon.document.MailLink;
import kameleon.document.NumberedListElement;
import kameleon.document.Paragraph;
import kameleon.document.Paragraphs;
import kameleon.document.Row;
import kameleon.document.Text;
import kameleon.document.TextParagraph;
import kameleon.document.TextParagraphElement;
import kameleon.document.Title;
import kameleon.exception.InvalidPropertyException;
import kameleon.plugin.SupportedOptions;
/**
* //TODO
*
* @author Schnell Michaël
* @version 1.0
*/
public class DocumentBodyGenerator
implements WordConstants, GenerationConstants, WordTags, ElementPropertiesDefaultNames {
public static final Hashtable<String, String> FORMAT_WORD =
new Hashtable<String, String>() {{
put(ElementPropertiesDefaultNames.FORMAT_BOLD, WordTags.FORMAT_BOLD) ;
put(ElementPropertiesDefaultNames.FORMAT_ITALIC, WordTags.FORMAT_ITALIC) ;
put(ElementPropertiesDefaultNames.FORMAT_STRUCK, WordTags.FORMAT_STRUCK) ;
put(ElementPropertiesDefaultNames.FORMAT_SUPERSCRIPT, WordTags.FORMAT_SUPERSCRIPT) ;
put(ElementPropertiesDefaultNames.FORMAT_SUBSCRIPT, WordTags.FORMAT_SUBSCRIPT) ;
}} ;
protected boolean debugMode ;
//TODO Add javadoc
protected File targetFile ;
protected Document base ;
protected SupportedOptions options ;
/**
* Sole constructor.
*/
public DocumentBodyGenerator(boolean debugMode) {
super() ;
this.debugMode = debugMode ;
}// DocumentBodyGenerator()
/**
* Generates the XML code for the {@code <w:body>} tag of the document.
*
* @return XML code for the {@code <w:body>} tag of the document
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*/
protected String generateBody() throws WordGenerationException {
return this.generate(this.base.getParagraphs()) ;
}// generateBody()
/**
* Generates the XML code for the given list of paragraphs.
*
* @param paragrahs
* instance of {@code Paragraphs} containing the list of paragraphs
*
* @return XML code for the given list of paragraphs
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*/
private String generate(Paragraphs paragrahs) throws WordGenerationException {
final Class<?> thisClass = DocumentBodyGenerator.class ;
StringBuilder body = new StringBuilder() ;
for (Paragraph p : paragrahs) {
try {
Method method = thisClass.getDeclaredMethod(
GENERATE_FUNCTION, p.getClass()) ;
body.append(method.invoke(this, p)) ;
} catch (Exception ex) {
// if (this.debugMode) {
// throw new WordGenerationException(this.targetFile) ;
// }// if
}// try
}// for
return body.toString() ;
}// generate(Paragraphs)
/**
* Generates the XML code for a {@code TextParagraph}.
*
* <p>The generated code start with a {@code <w:p>} tag and
* contains the given text.
*
* @param tp
* source for the generated text
*
* @return XML code for a {@code TextParagraph}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*/
protected String generate(TextParagraph tp) throws WordGenerationException {
final Class<?> thisClass = DocumentBodyGenerator.class ;
StringBuilder textP = new StringBuilder() ;
textP.append(PARAGRAPH_START) ;
for(TextParagraphElement pe : tp) {
try {
Method methode = thisClass.getDeclaredMethod(
GENERATE_FUNCTION, pe.getClass()) ;
textP.append(methode.invoke(this, pe)) ;
} catch (Exception ex) {
if (this.debugMode) {
throw new WordGenerationException(this.targetFile, ex) ;
}// if
}// try
}// for
textP.append(PARAGRAPH_END);
return textP.toString() ;
}// generate(TextParagraph)
/**
* Generates the XML code for a {@code BulletListElement}.
*
* <p>The generated code start with a {@code <w:p>} tag and
* contains the given text.
*
* @param element
* source for the generated text
*
* @return XML code for a {@code BulletListElement}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(BulletListElement element)
throws WordGenerationException, InvalidPropertyException {
return this.generate(element, BULLET_LIST_ID) ;
}// generate(BulletListElement)
/**
* Generates the XML code for a {@code NumberedListElement}.
*
* <p>The generated code start with a {@code <w:p>} tag and
* contains the given text.
*
* @param element
* source for the generated text
*
* @return XML code for a {@code NumberedListElement}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(NumberedListElement element)
throws WordGenerationException, InvalidPropertyException {
return this.generate(element, NUMBERED_LIST_ID) ;
}// generate(NumberedListElement)
/**
* Generates the XML code for a {@code ListElement}.
*
* <p>The generated code start with a {@code <w:p>} tag and
* contains the given text.
*
* @param listElem
* source for the generated text
*
* @param id
* list style identifier used for this list element
*
* @return XML code for a {@code ListElement}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
private String generate(ListElement listElem, Integer id)
throws WordGenerationException, InvalidPropertyException {
final Class<?> thisClass = DocumentBodyGenerator.class ;
StringBuilder element = new StringBuilder() ;
element.append(String.format(LIST_ELEMENT_START,
listElem.getProperty(LIST_LEVEL), id)) ;
for(TextParagraphElement pe : listElem) {
try {
Method methode = thisClass.getDeclaredMethod(
GENERATE_FUNCTION, pe.getClass()) ;
element.append(methode.invoke(this, pe)) ;
} catch (Exception ex) {
if (this.debugMode) {
throw new WordGenerationException(this.targetFile, ex) ;
}// if
}// try
}// for
element.append(LIST_ELEMENT_END);
return element.toString() ;
}// generate(ListElement)
/**
* Generates the XML code for a {@code TextParagraph}.
*
* <p>The generated code start with a {@code <w:p>} tag and
* contains the given text.
*
* @param title
* source for the generated text
*
* @return XML code for a {@code TextParagraph}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(Title title)
throws WordGenerationException, InvalidPropertyException {
StringBuilder titleP = new StringBuilder() ;
String styleName = String.format(HEADING_NAME,
title.getProperty(TITLE_LEVEL)) ;
String content = escape((String) title.getProperty(TEXT_BODY)) ;
titleP.append(PARAGRAPH_START) ;
titleP.append(String.format(PARAGRAPH_PROPERTIES, styleName)) ;
titleP.append(RUN_START) ;
titleP.append(TEXT_START) ;
titleP.append(content) ;
titleP.append(TEXT_END) ;
titleP.append(RUN_END) ;
titleP.append(PARAGRAPH_END) ;
return titleP.toString() ;
}// generate(Title)
/**
* Generates the XML code for a {@code Array}.
*
* @param array
* source for the generated array
*
* @return XML code for a {@code Array}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(Array array)
throws WordGenerationException, InvalidPropertyException {
StringBuilder arrayP = new StringBuilder() ;
arrayP.append(ARRAY_START) ;
arrayP.append(ARRAY_PROPERTIES) ;
arrayP.append(ARRAY_PROPERTIES_GRID_WIDTH_START) ;
int nCols = array.iterator().next().getCount() ;
Integer colWidth = new Integer(
DEFAULT_TABLE_WIDTH.intValue() / nCols) ;
for(int col=0; col<nCols; ++col) {
arrayP.append(String.format(ARRAY_PROPERTIES_GRID_WIDTH,
colWidth)) ;
}// for
arrayP.append(ARRAY_PROPERTIES_GRID_WIDTH_END) ;
for(Row row : array) {
arrayP.append(this.generate(row)) ;
}// for
arrayP.append(ARRAY_END) ;
return arrayP.toString() ;
}// generate(Array)
/**
* Generates the XML code for a {@code Row}.
*
* @param row
* source for the generated row
*
* @return XML code for a {@code Row}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(Row row)
throws WordGenerationException, InvalidPropertyException {
// final Class<?> thisClass = DocumentBodyGenerator.class ;
StringBuilder rowP = new StringBuilder() ;
rowP.append(ROW_START) ;
for(Cell cell : row) {
// try {
// Method methode = thisClass.getDeclaredMethod(
// GENERATE_FUNCTION, cell.getClass()) ;
// rowP.append(methode.invoke(this, cell)) ;
// } catch (Exception ex) {
// if (this.debugMode) {
// throw new WordGenerationException(this.targetFile) ;
// }// if
// }// try
rowP.append(this.generate(cell)) ;
}// for
rowP.append(ROW_END) ;
return rowP.toString() ;
}// generate(Row)
/**
* Generates the XML code for a {@code Cell}.
*
* @param cell
* source for the generated cell
*
* @return XML code for a {@code Cell}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(Cell cell)
throws WordGenerationException, InvalidPropertyException {
StringBuilder cellP = new StringBuilder() ;
boolean generateContent = true ;
cellP.append(CELL_START) ;
if (Boolean.TRUE.equals(cell.getProperty(ROW_SPAN))) {
cellP.append(CELL_ROW_SPAN) ;
generateContent = false ;
}// if
if (Boolean.TRUE.equals(cell.getProperty(COL_SPAN))) {
cellP.append(CELL_COL_SPAN) ;
generateContent = false ;
}// if
if (generateContent) {
cellP.append(this.generate(cell.getParagraphs())) ;
}// if
cellP.append(CELL_END) ;
return cellP.toString() ;
}// generate(Cell)
/**
* Generates the XML code for a {@code HorizontalSeparator}.
*
* @param separator
* source for the generated separator
*
* @return XML code for a {@code HorizontalSeparator}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(HorizontalSeparator separator)
throws WordGenerationException, InvalidPropertyException {
return HORIZONTAL_SEPARATOR ;
}// generate(HorizontalSeparator)
/**
* Generates the XML code for a {@code Text}.
*
* @param text
* source for the generated text
*
* @return XML code for a {@code Text}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(Text text)
throws WordGenerationException, InvalidPropertyException {
StringBuilder textP = new StringBuilder() ;
String content = escape((String) text.getProperty(TEXT_BODY)) ;
textP.append(RUN_START) ;
textP.append(RUN_PROPERTIES_START) ;
for(String format : FORMAT_WORD.keySet()) {
if (Boolean.TRUE.equals(text.getProperty(format))) {
textP.append(FORMAT_WORD.get(format)) ;
}// if
}// for
textP.append(RUN_PROPERTIES_END) ;
textP.append(TEXT_START) ;
textP.append(content) ;
textP.append(TEXT_END) ;
textP.append(RUN_END) ;
return textP.toString() ;
}// generate(Text)
/**
* Generates the XML code for a {@code LineBreak}.
*
* @param lineBreak
* source for the generated line break
*
* @return XML code for a {@code LineBreak}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(LineBreak lineBreak)
throws WordGenerationException, InvalidPropertyException {
return LINE_BREAK ;
}// generate(LineBreak)
/**
* Generates the XML code for a {@code MailLink}.
*
* @param link
* source for the generated link
*
* @return XML code for a {@code MailLink}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(MailLink link)
throws WordGenerationException, InvalidPropertyException {
final Class<?> thisClass = DocumentBodyGenerator.class ;
StringBuilder mailP = new StringBuilder() ;
String destination = (String) link.getProperty(MAIL_DESTINATION) ;
mailP.append(String.format(MAIL_LINK_START, destination)) ;
mailP.append(RUN_START) ;
mailP.append(LINK_RUN) ;
for(TextParagraphElement pe : link){
try {
Method methode = thisClass.getDeclaredMethod(
GENERATE_FUNCTION, pe.getClass()) ;
mailP.append(methode.invoke(this, pe)) ;
} catch (Exception ex) {
if (this.debugMode) {
throw new WordGenerationException(this.targetFile, ex) ;
}// if
}// try
}// for
mailP.append(RUN_END) ;
mailP.append(MAIL_LINK_END) ;
return mailP.toString() ;
}// generate(MailLink)
/**
* Generates the XML code for a {@code HyperTextLink}.
*
* @param link
* source for the generated link
*
* @return XML code for a {@code HyperTextLink}
*
* @throws WordGenerationException
* if an error occurred while generating the XML code
*
* @throws InvalidPropertyException
* if an invalid key was requested
*/
protected String generate(HyperTextLink link)
throws WordGenerationException, InvalidPropertyException {
final Class<?> thisClass = DocumentBodyGenerator.class ;
StringBuilder mailP = new StringBuilder() ;
String destination = (String) link.getProperty(MAIL_DESTINATION) ;
mailP.append(String.format(HYPERTEXT_LINK_START, destination)) ;
mailP.append(RUN_START) ;
mailP.append(LINK_RUN) ;
for(TextParagraphElement pe : link){
try {
Method methode = thisClass.getDeclaredMethod(
GENERATE_FUNCTION, pe.getClass()) ;
mailP.append(methode.invoke(this, pe)) ;
} catch (Exception ex) {
if (this.debugMode) {
throw new WordGenerationException(this.targetFile, ex) ;
}// if
}// try
}// for
mailP.append(RUN_END) ;
mailP.append(HYPERTEXT_LINK_END) ;
return mailP.toString() ;
}// generate(HyperTextLink)
/**
* Escapes the special characters of the given {@code String} so
* that they can be inserted in a XML file.
*
* <p>The following characters are currently escaped:
* <ul>
* <li>{@code & --> &}
* <li>{@code < --> <}
* <li>{@code > --> >}
* </ul>
*
* @param str
* text which should be escaped
*
* @return escaped version of {@code str}
*/
public static String escape(String str) {
return str.replaceAll("&", "&") //$NON-NLS-1$//$NON-NLS-2$
.replaceAll("<", "<") //$NON-NLS-1$ //$NON-NLS-2$
.replaceAll(">", ">") ; //$NON-NLS-1$ //$NON-NLS-2$
}// escape(String)
}// class DocumentBodyGenerator