Newer
Older
marking / src / main / java / report / FeedbackReportGenerator.java
package report;

import dao.MarkingProperties;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Map;
import javax.swing.JOptionPane;
import model.Student;
import static net.sf.dynamicreports.report.builder.DynamicReports.cmp;
import static net.sf.dynamicreports.report.builder.DynamicReports.field;
import static net.sf.dynamicreports.report.builder.DynamicReports.grp;
import static net.sf.dynamicreports.report.builder.DynamicReports.margin;
import static net.sf.dynamicreports.report.builder.DynamicReports.report;
import static net.sf.dynamicreports.report.builder.DynamicReports.stl;
import static net.sf.dynamicreports.report.builder.DynamicReports.template;
import static net.sf.dynamicreports.report.builder.DynamicReports.type;
import net.sf.dynamicreports.report.builder.FieldBuilder;
import net.sf.dynamicreports.report.builder.component.HorizontalListBuilder;
import net.sf.dynamicreports.report.builder.group.CustomGroupBuilder;
import net.sf.dynamicreports.report.builder.style.StyleBuilder;
import net.sf.dynamicreports.report.constant.HorizontalTextAlignment;
import net.sf.dynamicreports.report.constant.LineStyle;
import net.sf.dynamicreports.report.constant.VerticalTextAlignment;
import net.sf.dynamicreports.report.exception.DRException;
import net.sf.jasperreports.engine.data.JRMapCollectionDataSource;

/**
 *
 * @author Mark George <mark.george@otago.ac.nz>
 */
public class FeedbackReportGenerator {

	private final Collection<Map<String, ?>> data;
	private final String outputDirectory;
	private final String fileNamePrefix;
	private final String title;
	private final String footer;

	public FeedbackReportGenerator(Collection<Map<String, ?>> data, String outputDirectory, String fileNamePrefix, String title, String footer) {
		this.data = data;
		this.outputDirectory = outputDirectory;
		this.fileNamePrefix = fileNamePrefix;
		this.title = title;
		this.footer = footer;
	}

	public void generate(Student student) {

		if (!Files.exists(Paths.get(this.outputDirectory))) {
			JOptionPane.showMessageDialog(null, "Report folder does not exist.  Please create it.\n\nPath should be:\n" + this.outputDirectory, "Report Folder Does Not Exist", JOptionPane.WARNING_MESSAGE);
			throw new RuntimeException("Report folder does not exist");
		}

		StyleBuilder labelSty
			= stl.style()
				.bold()
				.setHorizontalTextAlignment(HorizontalTextAlignment.RIGHT)
				.setVerticalTextAlignment(VerticalTextAlignment.MIDDLE);

		StyleBuilder valSty
			= stl.style()
				.setHorizontalTextAlignment(HorizontalTextAlignment.LEFT)
				.setVerticalTextAlignment(VerticalTextAlignment.MIDDLE);

		StyleBuilder markSty
			= stl.style()
				.bold()
				.setHorizontalTextAlignment(HorizontalTextAlignment.RIGHT)
				.setVerticalTextAlignment(VerticalTextAlignment.MIDDLE);

		StyleBuilder criterionSty
			= stl.style()
				.bold()
				.setHorizontalTextAlignment(HorizontalTextAlignment.LEFT)
				.setVerticalTextAlignment(VerticalTextAlignment.MIDDLE);

		FieldBuilder<String> assessment = field("ASSESSMENT", type.stringType());
		FieldBuilder<BigDecimal> outOf = field("OUT_OF", type.bigDecimalType());
		FieldBuilder<String> id = field("STUDENT_ID", type.stringType());
		FieldBuilder<String> name = field("NAME", type.stringType());
		FieldBuilder<BigDecimal> mark = field("MARK", type.bigDecimalType());

		FieldBuilder<String> category = field("CATEGORY", type.stringType());

		CustomGroupBuilder categoryGroup = grp.group(category)
			.setStyle(stl.style().bold().setFontSize(13));

		FieldBuilder<String> criterion = field("CRITERION", type.stringType());
		FieldBuilder<BigDecimal> result = field("RESULT", type.bigDecimalType());
		FieldBuilder<BigDecimal> max = field("MAX", type.bigDecimalType());
		FieldBuilder<String> comment = field("COMMENT", type.stringType());

		HorizontalListBuilder marksHeader;
		HorizontalListBuilder marksDetails;

		if (MarkingProperties.reportShowMax()) {

			marksHeader = cmp.horizontalList().add(
				cmp.text("").setStyle(criterionSty).setWidth(50),
				cmp.text("Mark").setStyle(markSty).setWidth(4),
				cmp.text("/").setStyle(labelSty).setWidth(1),
				cmp.horizontalGap(5),
				cmp.text("Max").setStyle(valSty).setWidth(3)
			);

			marksDetails = cmp.horizontalList()
				.add(
					cmp.text(criterion).setStyle(criterionSty).setWidth(50),
					cmp.text(result).setStyle(markSty).setWidth(4),
					cmp.text("/").setStyle(labelSty).setWidth(1),
					cmp.horizontalGap(5),
					cmp.text(max).setStyle(valSty).setWidth(3)
				);

		} else {
			marksHeader = cmp.horizontalList().add(
				cmp.text("").setStyle(criterionSty).setWidth(50),
				cmp.text("Mark").setStyle(markSty).setWidth(4)
			);

			marksDetails = cmp.horizontalList().add(
				cmp.text(criterion).setStyle(criterionSty).setWidth(50),
				cmp.text(result).setStyle(markSty).setWidth(4)
			);
		}

		try {
			// header
			report()
				.setTemplate(template().setPageMargin(margin(50)))
				.setDataSource(new JRMapCollectionDataSource(data))
				.title(
					cmp.text(title).setStyle(stl.style().setFontSize(14).bold()),
					cmp.verticalGap(10),
					cmp.horizontalList()
						.add(
							cmp.text("Assessment:").setStyle(labelSty).setWidth(18),
							cmp.horizontalGap(5),
							cmp.text(assessment).setStyle(valSty)
						)
						.newRow().add(
							cmp.text("ID:").setStyle(labelSty).setWidth(18),
							cmp.horizontalGap(5),
							cmp.text(id).setStyle(valSty)
						)
						.newRow().add(
							cmp.text("Name:").setStyle(labelSty).setWidth(18),
							cmp.horizontalGap(5),
							cmp.text(name).setStyle(valSty)
						)
						.newRow().add(
							cmp.text("Mark:").setStyle(labelSty).setWidth(18),
							cmp.horizontalGap(5),
							cmp.text(mark).setStyle(valSty)
						)
						.newRow().add(
							cmp.text("Out of:").setStyle(labelSty).setWidth(18),
							cmp.horizontalGap(5),
							cmp.text(outOf).setStyle(valSty)
						),
					cmp.verticalGap(15)
				)
				// details

				.groupBy(categoryGroup).groupHeader(categoryGroup,
				marksHeader,
				cmp.line().setPen(stl.pen(2.0f, LineStyle.DOUBLE)))
				.detail(
					cmp.verticalGap(1),
					marksDetails,
					cmp.horizontalList(
						cmp.horizontalGap(11),
						cmp.text(comment).removeLineWhenBlank()
					).setMinHeight(0),
					cmp.verticalGap(1),
					cmp.line().setPen(stl.penThin())
				)
				.groupFooter(categoryGroup, cmp.verticalGap(18))
				.summary(cmp.text(footer))
				//				.summary(cmp.text("The mark for the bonus tasks is only applied if you lost marks in other components (including the UML diagrams and security audit).  In other words, your total mark is capped at 25."))
				.pageFooter(cmp.pageXofY().setStyle(stl.style().bold()))
				//				.show()

				.toPdf(new FileOutputStream(outputDirectory + "/" + fileNamePrefix + "-" + student.getId() + ".pdf"));
		} catch (FileNotFoundException | DRException ex) {
			throw new RuntimeException(ex);
		}

	}

}