package org.activityinfo.server.report.renderer.itext;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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/gpl-3.0.html>.
* #L%
*/
import com.google.code.appengine.awt.Color;
import com.google.code.appengine.awt.Graphics2D;
import com.google.inject.Inject;
import com.lowagie.text.*;
import org.activityinfo.i18n.shared.I18N;
import org.activityinfo.legacy.shared.model.IndicatorDTO;
import org.activityinfo.legacy.shared.reports.content.*;
import org.activityinfo.legacy.shared.reports.model.MapReportElement;
import org.activityinfo.legacy.shared.reports.model.layers.MapLayer;
import org.activityinfo.legacy.shared.reports.model.layers.PiechartMapLayer;
import org.activityinfo.legacy.shared.reports.model.layers.PiechartMapLayer.Slice;
import org.activityinfo.server.geo.AdminGeometryProvider;
import org.activityinfo.server.report.generator.MapIconPath;
import org.activityinfo.server.report.renderer.image.*;
import org.activityinfo.server.report.util.ColorUtil;
import java.io.File;
import java.io.IOException;
/**
* Renders a {@link org.activityinfo.legacy.shared.reports.model.MapReportElement
* MapElement} into an iText document
*/
public class ItextMapRenderer extends ImageMapRenderer implements ItextRenderer<MapReportElement> {
private ImageCreator imageCreator;
private ItextGraphic graphic;
@Inject
public ItextMapRenderer(AdminGeometryProvider geometryProvider,
@MapIconPath String mapIconPath,
ImageCreator imageCreator) {
super(geometryProvider, mapIconPath);
this.imageCreator = imageCreator;
}
@Override
public void render(DocWriter writer, Document doc, MapReportElement element) {
try {
doc.add(ThemeHelper.elementTitle(element.getTitle()));
ItextRendererHelper.addFilterDescription(doc, element.getContent().getFilterDescriptions());
ItextRendererHelper.addDateFilterDescription(doc, element.getFilter().getDateRange());
renderMap(writer, element, doc);
if (!element.getContent().getLegends().isEmpty()) {
renderLegend(element, doc);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void renderMap(DocWriter writer,
MapReportElement element,
Document doc) throws BadElementException, DocumentException {
graphic = imageCreator.createMap(element.getWidth(), element.getHeight());
drawBasemap(element, new ItextTileHandler(graphic));
drawOverlays(element, graphic.getGraphics());
doc.add(graphic.toItextImage());
}
@Override
protected void drawIcon(Graphics2D g2d, IconMapMarker marker) {
int x = marker.getX() - marker.getIcon().getAnchorX();
int y = marker.getY() - marker.getIcon().getAnchorY();
File imageFile = getImageFile(marker.getIcon().getName());
try {
Image image = Image.getInstance(imageFile.getAbsolutePath());
image.setAbsolutePosition(x, y);
graphic.addImage(imageFile.toURI().toURL().toString(),
x,
y,
marker.getIcon().getWidth(),
marker.getIcon().getHeight());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void renderLegend(MapReportElement element, Document doc) throws DocumentException, IOException {
Table table = new Table(2);
table.setBorderWidth(1);
table.setWidth(100f);
table.setBorderColor(new Color(100, 100, 100));
table.setPadding(5);
table.setSpacing(0);
table.setCellsFitPage(true);
table.setTableFitsPage(true);
table.setWidths(new int[]{1, 3});
Cell cell = new Cell(I18N.CONSTANTS.legend());
cell.setHeader(true);
cell.setColspan(2);
table.addCell(cell);
table.endHeaders();
for (MapLayerLegend legend : element.getContent().getLegends()) {
Cell symbolCell = new Cell();
symbolCell.setHorizontalAlignment(Element.ALIGN_CENTER);
symbolCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
Image symbol = createLegendSymbol(legend, imageCreator);
symbolCell.addElement(symbol);
Cell descriptionCell = new Cell();
addLegendDescription(element, legend.getDefinition(), descriptionCell);
table.addCell(symbolCell);
table.addCell(descriptionCell);
}
doc.add(table);
}
private void addLegendDescription(MapReportElement element,
MapLayer layer,
Cell descriptionCell) throws BadElementException, IOException {
if (layer instanceof PiechartMapLayer) {
addPieChartDescription(element, descriptionCell, (PiechartMapLayer) layer);
} else if (layer.getIndicatorIds().size() == 1) {
addSingleIndicatorDescription(element, layer, descriptionCell);
} else {
addIndicatorList(element, layer, descriptionCell);
}
}
private void addPieChartDescription(MapReportElement element,
Cell descriptionCell,
PiechartMapLayer layer) throws BadElementException, IOException {
for (Slice slice : layer.getSlices()) {
IndicatorDTO indicator = element.getContent().getIndicatorById(slice.getIndicatorId());
Color color = ColorUtil.colorFromString(slice.getColor());
ItextGraphic sliceImage = renderSlice(imageCreator, color, 10);
Chunk box = new Chunk(sliceImage.toItextImage(), 0, 0);
Chunk description = new Chunk(indicator.getName());
Phrase phrase = new Phrase();
phrase.add(box);
phrase.add(description);
Paragraph paragraph = new Paragraph(phrase);
descriptionCell.add(paragraph);
}
}
private void addSingleIndicatorDescription(MapReportElement element, MapLayer layer, Cell descriptionCell) {
int indicatorId = layer.getIndicatorIds().get(0);
IndicatorDTO indicator = element.getContent().getIndicatorById(indicatorId);
if (indicator == null) {
throw new NullPointerException("indicatorId:" + indicatorId);
}
descriptionCell.add(ThemeHelper.filterDescription(indicator.getName()));
}
private void addIndicatorList(MapReportElement element, MapLayer layer, Cell descriptionCell) {
com.lowagie.text.List list = new List(List.UNORDERED);
for (int indicatorId : layer.getIndicatorIds()) {
IndicatorDTO indicator = element.getContent().getIndicatorById(indicatorId);
list.add(new ListItem(indicator.getName()));
}
descriptionCell.add(list);
}
public Image createLegendSymbol(MapLayerLegend<?> legend, ImageCreator creator) throws BadElementException {
if (legend instanceof BubbleLayerLegend) {
return new BubbleLegendRenderer((BubbleLayerLegend) legend).createImage(creator).toItextImage();
} else if (legend instanceof IconLayerLegend) {
return createIconImage((IconLayerLegend) legend);
} else if (legend instanceof PieChartLegend) {
return new PieChartLegendRenderer((PieChartLegend) legend).createImage(creator).toItextImage();
} else if (legend instanceof PolygonLegend) {
return new PolygonLegendRenderer((PolygonLegend) legend).createImage(creator).toItextImage();
} else {
throw new IllegalArgumentException();
}
}
private Image createIconImage(IconLayerLegend legend) {
try {
return Image.getInstance(getImageFile(legend.getDefinition().getIcon()).getAbsolutePath());
} catch (Exception e) {
throw new RuntimeException("Can't create image for " + legend.getDefinition().getIcon());
}
}
}