/*
* Copyright (C) 2003-2011 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.wiki.rendering.macro.section;
import java.io.StringReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.Requirement;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.rendering.block.Block;
import org.xwiki.rendering.block.GroupBlock;
import org.xwiki.rendering.block.MacroBlock;
import org.xwiki.rendering.block.XDOM;
import org.xwiki.rendering.macro.AbstractMacro;
import org.xwiki.rendering.macro.MacroExecutionException;
import org.xwiki.rendering.parser.ParseException;
import org.xwiki.rendering.parser.Parser;
import org.xwiki.rendering.transformation.MacroTransformationContext;
/**
* Created by The eXo Platform SAS
* Author : Lai Trung Hieu
* hieu.lai@exoplatform.com
* 15 Mar 2011
*/
@Component("section")
public class SectionMacro extends AbstractMacro<SectionMacroParameters> {
private static final double TOTAL_WIDTH = 99.900000000000006D;
private static final double COLUMN_RIGHT_PADDING_RATE = 1.5D;
private static final String STYLE_TEXT_ALIGN_JUSTIFY = "text-align:justify;";
private static final String STYLE_CLEAR_BOTH = "clear:both";
private static final String PARAMETER_STYLE = "style";
private static final String COLUMN_RIGHT_PADDING_STYLE = "1.5%";
private static final String DESCRIPTION = "A macro to enclose columned text";
private static final String MACRO_NAME = "Section";
@Requirement
private ComponentManager componentManager;
public SectionMacro() {
super(MACRO_NAME, DESCRIPTION, SectionMacroParameters.class);
}
public List<Block> execute(SectionMacroParameters parameters,
String content,
MacroTransformationContext context) throws MacroExecutionException {
Parser parser = getSyntaxParser(context.getSyntax().toIdString());
XDOM parsedDom;
try {
parsedDom = parser.parse(new StringReader(content));
} catch (ParseException e) {
throw new MacroExecutionException("Failed to parse content [" + content
+ "] with Syntax parser [" + parser.getSyntax() + "]", e);
}
List<MacroBlock> potentialColumns = parsedDom.getChildrenByType(MacroBlock.class, false);
int count = countColumns(potentialColumns);
if (count == 0) {
throw new MacroExecutionException("Section macro expect at least one column macro as first-level children");
}
double computedColumnWidth = (TOTAL_WIDTH - COLUMN_RIGHT_PADDING_RATE * (count - 1)) / count;
makeColumns(potentialColumns, computedColumnWidth);
Map<String, String> clearFloatsParams = new HashMap<String, String>();
clearFloatsParams.put(PARAMETER_STYLE, STYLE_CLEAR_BOTH);
parsedDom.addChild(new GroupBlock(clearFloatsParams));
Map<String, String> sectionParameters = new HashMap<String, String>();
if (parameters.isJustify()) {
sectionParameters.put(PARAMETER_STYLE, STYLE_TEXT_ALIGN_JUSTIFY);
}
Block sectionRoot = new GroupBlock(sectionParameters);
sectionRoot.addChildren(parsedDom.getChildren());
return Collections.singletonList(sectionRoot);
}
private int countColumns(List<MacroBlock> blocks) {
int result = 0;
for (MacroBlock maybeColumn : blocks) {
if (maybeColumn.getId().equals("column")) {
result++;
}
}
return result;
}
private void makeColumns(List<MacroBlock> blocks, double columnWidth) {
Iterator<MacroBlock> it = blocks.iterator();
while (it.hasNext()) {
MacroBlock probablyColumn = (MacroBlock) it.next();
if (probablyColumn.getId().equals("column")) {
ColumnStyle style = new ColumnStyle();
style.setWidth(columnWidth + "%");
if (it.hasNext()) {
style.setPaddingRight(COLUMN_RIGHT_PADDING_STYLE);
}
Map<String, String> params = Collections.singletonMap(PARAMETER_STYLE,
style.getStyleAsString());
Block colParent = new GroupBlock(new HashMap<String, String>(params));
colParent.addChild(probablyColumn.clone());
probablyColumn.getParent().replaceChild(colParent, probablyColumn);
}
}
}
protected Parser getSyntaxParser(String syntaxId) throws MacroExecutionException {
try {
return (Parser) this.componentManager.lookup(Parser.class, syntaxId);
} catch (ComponentLookupException e) {
throw new MacroExecutionException("Failed to find source parser", e);
}
}
public boolean supportsInlineMode() {
return false;
}
public int getPriority() {
return 750;
}
}