blob: c9608359bb56b42531a7ac27462f378cf5569612 [file] [log] [blame]
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.poi.xslf.usermodel;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.List;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.AxisCrossBetween;
import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
import org.apache.poi.xddf.usermodel.chart.AxisOrientation;
import org.apache.poi.xddf.usermodel.chart.AxisPosition;
import org.apache.poi.xddf.usermodel.chart.AxisTickMark;
import org.apache.poi.xddf.usermodel.chart.BarDirection;
import org.apache.poi.xddf.usermodel.chart.BarGrouping;
import org.apache.poi.xddf.usermodel.chart.Grouping;
import org.apache.poi.xddf.usermodel.chart.LayoutMode;
import org.apache.poi.xddf.usermodel.chart.LayoutTarget;
import org.apache.poi.xddf.usermodel.chart.LegendPosition;
import org.apache.poi.xddf.usermodel.chart.RadarStyle;
import org.apache.poi.xddf.usermodel.chart.ScatterStyle;
import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFLineChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFManualLayout;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFPieChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFRadarChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFScatterChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.junit.jupiter.api.Test;
/**
* a modified version from POI-examples
*/
class TestXSLFChart {
@Test
void testFillPieChartTemplate() throws IOException {
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("pie-chart.pptx");
XSLFChart chart = findChart(pptx.getSlides().get(0));
List<XDDFChartData> data = findChartData(chart);
XDDFPieChartData pie = (XDDFPieChartData) data.get(0);
XDDFPieChartData.Series firstSeries = (XDDFPieChartData.Series) pie.getSeries(0);
firstSeries.setExplosion(25L);
assertEquals(Long.valueOf(25), firstSeries.getExplosion());
fillChartData(chart, pie);
pptx.close();
}
@Test
void testFillBarChartTemplate() throws IOException {
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("bar-chart.pptx");
XSLFSlide slide = pptx.getSlides().get(0);
// duplicate slide and chart before applying "destructive" tests to it
XSLFChart chart2 = findChart(pptx.createSlide().importContent(slide));
XSLFChart chart = findChart(slide);
List<XDDFChartData> data = findChartData(chart);
XDDFBarChartData bar = (XDDFBarChartData) data.get(0);
assertEquals(BarDirection.BAR, bar.getBarDirection());
assertEquals(BarGrouping.CLUSTERED, bar.getBarGrouping());
assertEquals(Integer.valueOf(100), bar.getGapWidth());
fillChartData(chart, bar);
XDDFBarChartData column = (XDDFBarChartData) findChartData(chart2).get(0);
column.setBarDirection(BarDirection.COL);
assertEquals(BarDirection.COL, column.getBarDirection());
column.getCategoryAxis().setOrientation(AxisOrientation.MIN_MAX);
column.getValueAxes().get(0).setPosition(AxisPosition.BOTTOM);
fillChartData(chart2, column);
pptx.close();
}
@Test
void testFillLineChartTemplate() throws IOException {
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("line-chart.pptx");
XSLFChart chart = findChart(pptx.getSlides().get(0));
List<XDDFChartData> data = findChartData(chart);
XDDFLineChartData line = (XDDFLineChartData) data.get(0);
assertEquals(Grouping.STANDARD, line.getGrouping());
line.setGrouping(Grouping.PERCENT_STACKED);
assertEquals(Grouping.PERCENT_STACKED, line.getGrouping());
fillChartData(chart, line);
pptx.close();
}
@Test
void testFillRadarChartTemplate() throws IOException {
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("radar-chart.pptx");
XSLFChart chart = findChart(pptx.getSlides().get(0));
List<XDDFChartData> data = findChartData(chart);
XDDFRadarChartData radar = (XDDFRadarChartData) data.get(0);
assertEquals(RadarStyle.MARKER, radar.getStyle());
radar.setStyle(RadarStyle.FILLED);
assertEquals(RadarStyle.FILLED, radar.getStyle());
fillChartData(chart, radar);
pptx.close();
}
@Test
void testFillScatterChartTemplate() throws IOException {
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("scatter-chart.pptx");
XSLFChart chart = findChart(pptx.getSlides().get(0));
List<XDDFChartData> data = findChartData(chart);
XDDFScatterChartData scatter = (XDDFScatterChartData) data.get(0);
assertEquals(ScatterStyle.LINE_MARKER, scatter.getStyle());
scatter.setStyle(ScatterStyle.SMOOTH);
assertEquals(ScatterStyle.SMOOTH, scatter.getStyle());
fillChartData(chart, scatter);
pptx.close();
}
private void fillChartData(XSLFChart chart, XDDFChartData data) {
final int numOfPoints = 3;
final String[] categories = {"First", "Second", "Third"};
final Integer[] values = {1, 3, 4};
final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
final XDDFChartData.Series series = data.getSeries(0);
final XDDFDataSource<?> categoryData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange);
final XDDFNumericalDataSource<Integer> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange);
series.replaceData(categoryData, valuesData);
final String title = "Apache POI";
series.setTitle(title, chart.setSheetTitle(title, 0));
chart.plot(data);
}
private XSLFChart findChart(XSLFSlide slide) {
// find chart in the slide
XSLFChart chart = null;
for(POIXMLDocumentPart part : slide.getRelations()){
if(part instanceof XSLFChart){
chart = (XSLFChart) part;
break;
}
}
if(chart == null) {
throw new IllegalStateException("chart not found in the template");
}
checkLegendOperations(chart);
return chart;
}
private List<XDDFChartData> findChartData(XSLFChart chart) {
List<XDDFChartData> data = chart.getChartSeries();
assertNotNull(data);
assertEquals(1, data.size());
XDDFChartData firstSeries = data.get(0);
assertNotNull(firstSeries);
if (firstSeries instanceof XDDFScatterChartData) {
assertNull(firstSeries.getCategoryAxis());
assertEquals(2, firstSeries.getValueAxes().size());
checkAxisOperations(firstSeries.getValueAxes().get(0));
checkAxisOperations(firstSeries.getValueAxes().get(1));
} else if (!(firstSeries instanceof XDDFPieChartData)) {
assertNotNull(firstSeries.getCategoryAxis());
assertEquals(1, firstSeries.getValueAxes().size());
checkAxisOperations(firstSeries.getValueAxes().get(0));
}
return data;
}
private void checkLegendOperations(XSLFChart chart) {
XDDFChartLegend legend = chart.getOrAddLegend();
assertFalse(legend.isOverlay());
legend.setOverlay(true);
assertTrue(legend.isOverlay());
legend.setPosition(LegendPosition.TOP_RIGHT);
assertEquals(LegendPosition.TOP_RIGHT, legend.getPosition());
XDDFManualLayout layout = legend.getOrAddManualLayout();
assertNotNull(layout.getTarget());
assertNotNull(layout.getXMode());
assertNotNull(layout.getYMode());
assertNotNull(layout.getHeightMode());
assertNotNull(layout.getWidthMode());
/*
* According to interface, 0.0 should be returned for
* uninitialized double properties.
*/
assertEquals(0.0, layout.getX(), 0.0);
assertEquals(0.0, layout.getY(), 0.0);
assertEquals(0.0, layout.getWidthRatio(), 0.0);
assertEquals(0.0, layout.getHeightRatio(), 0.0);
final double newRatio = 1.1;
final double newCoordinate = 0.3;
final LayoutMode nonDefaultMode = LayoutMode.FACTOR;
final LayoutTarget nonDefaultTarget = LayoutTarget.OUTER;
layout.setWidthRatio(newRatio);
assertEquals(layout.getWidthRatio(), newRatio, 0.0);
layout.setHeightRatio(newRatio);
assertEquals(layout.getHeightRatio(), newRatio, 0.0);
layout.setX(newCoordinate);
assertEquals(layout.getX(), newCoordinate, 0.0);
layout.setY(newCoordinate);
assertEquals(layout.getY(), newCoordinate, 0.0);
layout.setXMode(nonDefaultMode);
assertSame(layout.getXMode(), nonDefaultMode);
layout.setYMode(nonDefaultMode);
assertSame(layout.getYMode(), nonDefaultMode);
layout.setWidthMode(nonDefaultMode);
assertSame(layout.getWidthMode(), nonDefaultMode);
layout.setHeightMode(nonDefaultMode);
assertSame(layout.getHeightMode(), nonDefaultMode);
layout.setTarget(nonDefaultTarget);
assertSame(layout.getTarget(), nonDefaultTarget);
}
private void checkAxisOperations(XDDFValueAxis axis) {
axis.setCrossBetween(AxisCrossBetween.MIDPOINT_CATEGORY);
assertEquals(AxisCrossBetween.MIDPOINT_CATEGORY, axis.getCrossBetween());
axis.setCrosses(AxisCrosses.AUTO_ZERO);
assertEquals(AxisCrosses.AUTO_ZERO, axis.getCrosses());
final String numberFormat = "General";
axis.setNumberFormat(numberFormat);
assertEquals(numberFormat, axis.getNumberFormat());
axis.setPosition(AxisPosition.BOTTOM);
assertEquals(AxisPosition.BOTTOM, axis.getPosition());
axis.setMajorTickMark(AxisTickMark.NONE);
assertEquals(AxisTickMark.NONE, axis.getMajorTickMark());
axis.setMajorTickMark(AxisTickMark.IN);
assertEquals(AxisTickMark.IN, axis.getMajorTickMark());
axis.setMajorTickMark(AxisTickMark.OUT);
assertEquals(AxisTickMark.OUT, axis.getMajorTickMark());
axis.setMajorTickMark(AxisTickMark.CROSS);
assertEquals(AxisTickMark.CROSS, axis.getMajorTickMark());
axis.setMinorTickMark(AxisTickMark.NONE);
assertEquals(AxisTickMark.NONE, axis.getMinorTickMark());
axis.setMinorTickMark(AxisTickMark.IN);
assertEquals(AxisTickMark.IN, axis.getMinorTickMark());
axis.setMinorTickMark(AxisTickMark.OUT);
assertEquals(AxisTickMark.OUT, axis.getMinorTickMark());
axis.setMinorTickMark(AxisTickMark.CROSS);
assertEquals(AxisTickMark.CROSS, axis.getMinorTickMark());
axis.setVisible(true);
assertTrue(axis.isVisible());
axis.setVisible(false);
assertFalse(axis.isVisible());
final double EPSILON = 1E-7;
axis.setLogBase(Math.E);
assertTrue(Math.abs(axis.getLogBase() - Math.E) < EPSILON);
final double newValue = 10.0;
axis.setMinimum(newValue);
assertTrue(Math.abs(axis.getMinimum() - newValue) < EPSILON);
axis.setMaximum(newValue);
assertTrue(Math.abs(axis.getMaximum() - newValue) < EPSILON);
IllegalArgumentException iae = null;
try {
axis.setLogBase(0.0);
} catch (IllegalArgumentException e) {
iae = e;
}
assertNotNull(iae);
iae = null;
try {
axis.setLogBase(30000.0);
} catch (IllegalArgumentException e) {
iae = e;
}
assertNotNull(iae);
}
}