net.sf.jasperreports.engine.export.JRPdfExporterTagHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2022 TIBCO Software Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
/*
* Contributors:
* Adrian Jackson - [email protected]
* David Taylor - [email protected]
* Lars Kristensen - [email protected]
* Ling Li - [email protected]
* Martin Clough - [email protected]
*/
package net.sf.jasperreports.engine.export;
import java.util.Stack;
import net.sf.jasperreports.annotations.properties.Property;
import net.sf.jasperreports.annotations.properties.PropertyScope;
import net.sf.jasperreports.crosstabs.JRCellContents;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.JRPrintFrame;
import net.sf.jasperreports.engine.JRPrintImage;
import net.sf.jasperreports.engine.util.StyledTextListWriter;
import net.sf.jasperreports.export.AccessibilityUtil;
import net.sf.jasperreports.export.pdf.PdfProducer;
import net.sf.jasperreports.export.pdf.PdfStructure;
import net.sf.jasperreports.export.pdf.PdfStructureEntry;
import net.sf.jasperreports.export.type.AccessibilityTagEnum;
import net.sf.jasperreports.properties.PropertyConstants;
/**
* Provides support for tagged PDF documents.
*
* PDF files can contain hidden tags that describe the structure of the document. Some of
* the tags are used by the automated reader tool that reads PDF documents aloud to people
* with disabilities.
* Marking Headings
* JasperReports currently supports specifying type 1, 2 and 3 level headings.
* In order to mark a text field as a level 1 heading, the following custom element property
* should be used in JRXML:
*
* <property name="net.sf.jasperreports.export.pdf.tag.h1" value="full"/>
*
* Value full means that a full <H1>
tag will be embedded in the PDF wrapping the
* current text element.
* If two or more text fields make up a single level 1 heading, there are two ways to mark
* the heading:
*
* - In the first, the text elements making up the heading are placed inside a frame and
* the frame is marked with the following custom property:
*
* <property name="net.sf.jasperreports.export.pdf.tag.h1" value="full"/>
* - In the second, the first element of the heading (respective to the Z-Order, or the
* order in which the elements appear in JRXML) is tagged with:
*
* <property name="net.sf.jasperreports.export.pdf.tag.h1" value="start"/>
*
* and the last element from the heading (respective to the same order) is marked with
*
* <property name="net.sf.jasperreports.export.pdf.tag.h1" value="end"/>
*
*
* Level 2 and level 3 headings are marked the same way, except that the properties are:
*
* net.sf.jasperreports.export.pdf.tag.h2
*
* and
*
* net.sf.jasperreports.export.pdf.tag.h3
.
* Marking Tables
* Tables are comprised of column headers, row headers, and a data section. Each table
* section is made of cells. Marking table structures in PDF is similar to the way tables are
* described in HTML and uses the same techniques as those for marking headings.
*
* When marking a table, the user has to indicate in the report template where the table
* starts and where it ends.
*
* If the entire table is placed in a container, such as a frame element, marking the table
* requires only marking the parent frame with the following custom element property:
*
* <property name="net.sf.jasperreports.export.pdf.tag.table" value="full"/>
*
* However, most of the time, tables cannot be isolated in a frame unless they are
* subreports, because they generally span multiple report sections and bands. In such
* cases, marking a table requires marking in JRXML the first and last element making up
* the table structure.
*
* The first element of the table (probably the first element in the table header) should be
* marked with the following custom property:
*
* <property name="net.sf.jasperreports.export.pdf.tag.table" value="start"/>
*
* The last element of the table should be marked with:
*
* <property name="net.sf.jasperreports.export.pdf.tag.table" value="end"/>
*
* Tables are made of rows, and each row has to be precisely delimited within the table
* structure. This includes the column header rows at the top of the table. Similar to the
* headings and table marking, a table row can be identified in two ways:
*
* - If the entire content that makes up the row is isolated within a frame, the frame can be
* marked with the following custom property:
*
* <property name="net.sf.jasperreports.export.pdf.tag.tr" value="full"/>
*
* - If the content of the row is not grouped in a container frame, its first and last elements
* (respective to the Z-order or the order in which they appear in JRXML) have to be
* marked with the following custom properties:
*
* <property name="net.sf.jasperreports.export.pdf.tag.tr" value="start"/>
*
* for the first element and
*
* <property name="net.sf.jasperreports.export.pdf.tag.tr" value="start"/>
*
* for the last element.
*
*
* Each table row can contain header cells or data cells. Regardless of their type, and
* similar to headings, tables, and table rows, cells can be marked either by marking a
* single element representing the cell content (this single cell element can actually be a
* frame element), or by marking the first and last element from the cell content.
*
* Header cells made of a single element (this single element can actually be a frame) are
* marked with
*
* <property name="net.sf.jasperreports.export.pdf.tag.th" value="full"/>
*
* A header cell made of multiple elements is marked with
*
* <property name="net.sf.jasperreports.export.pdf.tag.th" value="start"/>
* on its first element and
*
* <property name="net.sf.jasperreports.export.pdf.tag.th" value="end"/>
* on its last element.
*
* Normal data cells made of a single element (that can be frame) are marked with
*
* <property name="net.sf.jasperreports.export.pdf.tag.td" value="full"/>
*
* Normal data cells made of multiple elements are marked with
*
* <property name="net.sf.jasperreports.export.pdf.tag.td" value="start"/>
* on their first element and
*
* <property name="net.sf.jasperreports.export.pdf.tag.td" value="end"/>
* on their last element.
*
* Just as in HTML tables, cells can span multiple rows and/or columns. Column span and
* row span values for the current table cell can be specified using the following custom
* properties on the same element where the cell start was marked (the element with the
* full or start property marking the cell):
*
* <property name="net.sf.jasperreports.export.pdf.tag.colspan" value="<number>"/>
*
* <property name="net.sf.jasperreports.export.pdf.tag.rowspan" value="<number>"/>
* PDF Content Reading Order
* JasperReports uses the Z-order of the elements as present in the report template
* (JRXML) to control reading order in the resulting PDF files. This is usually the intended
* way for the documents to be read, so no specific modifications were required in order to
* achieve it.
*
* @author Teodor Danciu ([email protected])
*/
public class JRPdfExporterTagHelper implements StyledTextListWriter
{
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_TABLE = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.table";
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_TR = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.tr";
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_TH = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.th";
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_TD = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.td";
/**
* @deprecated Replaced by styled text and HTML markup based bulleted and numbered lists.
*/
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_6_2_0
)
public static final String PROPERTY_TAG_L = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.l";
/**
* @deprecated Replaced by styled text and HTML markup based bulleted and numbered lists.
*/
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_6_2_0
)
public static final String PROPERTY_TAG_LI = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.li";
/**
* @deprecated Replaced by {@link AccessibilityUtil#PROPERTY_ACCESSIBILITY_TAG} and {@link AccessibilityTagEnum#H1}.
*/
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_H1 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h1";
/**
* @deprecated Replaced by {@link AccessibilityUtil#PROPERTY_ACCESSIBILITY_TAG} and {@link AccessibilityTagEnum#H2}.
*/
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_H2 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h2";
/**
* @deprecated Replaced by {@link AccessibilityUtil#PROPERTY_ACCESSIBILITY_TAG} and {@link AccessibilityTagEnum#H3}.
*/
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_H3 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h3";
/**
* @deprecated Replaced by {@link AccessibilityUtil#PROPERTY_ACCESSIBILITY_TAG} and {@link AccessibilityTagEnum#H4}.
*/
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_6_2_0
)
public static final String PROPERTY_TAG_H4 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h4";
/**
* @deprecated Replaced by {@link AccessibilityUtil#PROPERTY_ACCESSIBILITY_TAG} and {@link AccessibilityTagEnum#H5}.
*/
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_6_2_0
)
public static final String PROPERTY_TAG_H5 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h5";
/**
* @deprecated Replaced by {@link AccessibilityUtil#PROPERTY_ACCESSIBILITY_TAG} and {@link AccessibilityTagEnum#H6}.
*/
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_6_2_0
)
public static final String PROPERTY_TAG_H6 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h6";
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_COLSPAN = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.colspan";
@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.ELEMENT},
sinceVersion = PropertyConstants.VERSION_3_1_2
)
public static final String PROPERTY_TAG_ROWSPAN = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.rowspan";
public static final String TAG_START = "start";
public static final String TAG_END = "end";
public static final String TAG_FULL = "full";
protected JRPdfExporter exporter;
protected PdfProducer pdfProducer;
protected PdfStructure pdfStructure;
protected PdfStructureEntry allTag;
protected Stack tagStack;
protected boolean isTagEmpty = true;
protected int crtCrosstabRowY = -1;
protected boolean insideCrosstabCellFrame;
protected boolean isDataCellPrinted;
protected boolean isTagged;
protected String language;
/**
*
*/
protected JRPdfExporterTagHelper(JRPdfExporter exporter)
{
this.exporter = exporter;
}
/**
*
*/
protected void setTagged(boolean isTagged)
{
this.isTagged = isTagged;
}
/**
*
*/
protected void setLanguage(String language)
{
this.language = language;
}
/**
*
*/
protected void setPdfProducer(PdfProducer pdfProducer)
{
this.pdfProducer = pdfProducer;
this.pdfStructure = pdfProducer.getPdfStructure();
if (isTagged)
{
pdfProducer.setTagged();
}
}
/**
*
*/
protected void init()
{
if (isTagged)
{
allTag = pdfStructure.createAllTag(language);
tagStack = new Stack<>();
tagStack.push(allTag);
}
}
protected void startPageAnchor()
{
if (isTagged)
{
pdfStructure.beginTag(allTag, "Anchor");
}
}
protected void endPageAnchor()
{
if (isTagged)
{
pdfStructure.endTag();
}
}
protected void startPage()
{
crtCrosstabRowY = -1;
insideCrosstabCellFrame = false;
isDataCellPrinted = false;
}
protected void endPage()
{
if (isTagged)
{
if (crtCrosstabRowY >= 0) //crosstab still open
{
//end the current row
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
//end the table
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
}
}
}
protected void startElement(JRPrintElement element)
{
if (isTagged)
{
JRPrintFrame frame = element instanceof JRPrintFrame ? (JRPrintFrame) element : null;
boolean isCellContentsFrame =
frame != null
&& frame.getPropertiesMap().hasProperties()
&& frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE) != null;
if (isCellContentsFrame)
{
insideCrosstabCellFrame = true;
if (crtCrosstabRowY >= 0) //crosstab already started
{
if (JRCellContents.TYPE_DATA.equals(frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE)))
{
isDataCellPrinted = true;
}
if (crtCrosstabRowY != frame.getY())
{
//this is the first cell on a new row
//end the current row
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
if (
isDataCellPrinted
&& (JRCellContents.TYPE_CROSSTAB_HEADER.equals(frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE))
|| JRCellContents.TYPE_COLUMN_HEADER.equals(frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE)))
)
{
//end the table
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
//start table
createTableStartTag();
//start crosstab
isDataCellPrinted = false;
}
//start the new row
createTrStartTag();
//keep crosstab open, but mark new row position and frame depth
crtCrosstabRowY = frame.getY();
}
}
else
{
//start table and first row
createTableStartTag();
createTrStartTag();
//start crosstab
crtCrosstabRowY = frame.getY();
isDataCellPrinted = false;
}
}
else
{
if (crtCrosstabRowY >= 0) //crosstab already started
{
if (!insideCrosstabCellFrame)
{
//normal element outside crosstab
//end the current row
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
//end the table
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
//end crosstab
crtCrosstabRowY = -1;
}
}
// else
// {
// //normal element outside crosstab
// }
}
createStartTags(element);
}
}
protected void endElement(JRPrintElement element)
{
if (isTagged)
{
JRPrintFrame frame = element instanceof JRPrintFrame ? (JRPrintFrame) element : null;
boolean isCellContentsFrame =
frame != null
&& frame.getPropertiesMap().hasProperties()
&& frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE) != null;
if (isCellContentsFrame)
{
insideCrosstabCellFrame = false;
}
createEndTags(element);
}
}
protected void startImage(JRPrintImage printImage)
{
if (isTagged)
{
PdfStructureEntry imageTag = pdfStructure.beginTag(allTag, "Image");
if (printImage.getHyperlinkTooltip() != null)
{
imageTag.putString("Alt", printImage.getHyperlinkTooltip());
}
}
}
protected void endImage()
{
if (isTagged)
{
pdfStructure.endTag();
}
}
protected void startText(boolean isHyperlink)
{
if (isTagged)
{
// PdfStructureElement parentTag = tableCellTag == null ? (tableHeaderTag == null ? allTag : tableHeaderTag): tableCellTag;
// PdfStructureElement textTag = new PdfStructureElement(parentTag, PdfName.TEXT);
pdfStructure.beginTag(tagStack.peek(), isHyperlink ? "Link" : "Text");
}
}
protected void startText(String text, boolean isHyperlink)
{
if (isTagged)
{
pdfStructure.beginTag(tagStack.peek(), isHyperlink ? "Link" : "Text",
text);
}
}
protected void endText()
{
if (isTagged)
{
pdfStructure.endTag();
isTagEmpty = false;
}
}
protected void createStartTags(JRPrintElement element)
{
if (element.hasProperties())
{
String prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TABLE);
if (TAG_START.equals(prop) || TAG_FULL.equals(prop))
{
createTableStartTag();
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TR);
if (TAG_START.equals(prop) || TAG_FULL.equals(prop))
{
createTrStartTag();
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TH);
if (TAG_START.equals(prop) || TAG_FULL.equals(prop))
{
createThStartTag(element);
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TD);
if (TAG_START.equals(prop) || TAG_FULL.equals(prop))
{
createTdStartTag(element);
}
prop = element.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE);
if (
JRCellContents.TYPE_CROSSTAB_HEADER.equals(prop)
|| JRCellContents.TYPE_COLUMN_HEADER.equals(prop)
|| JRCellContents.TYPE_ROW_HEADER.equals(prop)
)
{
createThStartTag(element);
}
if (JRCellContents.TYPE_DATA.equals(prop))
{
createTdStartTag(element);
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_L);
if (TAG_START.equals(prop) || TAG_FULL.equals(prop))
{
createListStartTag();
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_LI);
if (TAG_START.equals(prop) || TAG_FULL.equals(prop))
{
createListItemStartTag(element);
}
createStartHeadingTags(element, PROPERTY_TAG_H1, AccessibilityTagEnum.H1);
createStartHeadingTags(element, PROPERTY_TAG_H2, AccessibilityTagEnum.H2);
createStartHeadingTags(element, PROPERTY_TAG_H3, AccessibilityTagEnum.H3);
createStartHeadingTags(element, PROPERTY_TAG_H4, AccessibilityTagEnum.H4);
createStartHeadingTags(element, PROPERTY_TAG_H5, AccessibilityTagEnum.H5);
createStartHeadingTags(element, PROPERTY_TAG_H6, AccessibilityTagEnum.H6);
}
}
protected void createStartHeadingTags(JRPrintElement element, String pdfTagProp, AccessibilityTagEnum accessibilityTag)
{
String accessibilityTagPropValue = element.getPropertiesMap().getProperty(AccessibilityUtil.PROPERTY_ACCESSIBILITY_TAG);
String pdfTagPropValue = element.getPropertiesMap().getProperty(pdfTagProp);
if (
accessibilityTag.getName().equals(accessibilityTagPropValue)
|| TAG_START.equals(pdfTagPropValue) || TAG_FULL.equals(pdfTagPropValue)
)
{
PdfStructureEntry headingTag = pdfStructure.createTag(tagStack.peek(), accessibilityTag.name());
//pdfContentByte.beginMarkedContentSequence(headingTag);
headingTag.putArray("K");
tagStack.push(headingTag);
isTagEmpty = true;
}
}
protected void createTableStartTag()
{
PdfStructureEntry tableTag = pdfStructure.createTag(allTag, "Table");
//pdfContentByte.beginMarkedContentSequence(tableTag);
tableTag.putArray("K");
tagStack.push(tableTag);
}
protected void createTrStartTag()
{
PdfStructureEntry tableRowTag = pdfStructure.createTag(tagStack.peek(), "TR");
//pdfContentByte.beginMarkedContentSequence(tableRowTag);
tableRowTag.putArray("K");
tagStack.push(tableRowTag);
}
protected void createThStartTag(JRPrintElement element)
{
PdfStructureEntry tableHeaderTag = pdfStructure.createTag(tagStack.peek(), "TH");
//pdfContentByte.beginMarkedContentSequence(tableHeaderTag);
tableHeaderTag.putArray("K");
tagStack.push(tableHeaderTag);
isTagEmpty = true;
createSpanTags(element, tableHeaderTag);
}
protected void createTdStartTag(JRPrintElement element)
{
PdfStructureEntry tableCellTag = pdfStructure.createTag(tagStack.peek(), "TD");
//pdfContentByte.beginMarkedContentSequence(tableCellTag);
tableCellTag.putArray("K");
tagStack.push(tableCellTag);
isTagEmpty = true;
createSpanTags(element, tableCellTag);
}
protected void createSpanTags(JRPrintElement element, PdfStructureEntry parentTag)
{
Integer colSpan = null;
try {
String colSpanProp = element.getPropertiesMap().getProperty(PROPERTY_TAG_COLSPAN);
if (colSpanProp != null) {
colSpan = Integer.valueOf(colSpanProp);
}
} catch (NumberFormatException e) {}
if (colSpan == null) {
try {
String colSpanProp = element.getPropertiesMap().getProperty(JRCellContents.PROPERTY_COLUMN_SPAN);
if (colSpanProp != null) {
colSpan = Integer.valueOf(colSpanProp);
}
} catch (NumberFormatException ex) {}
}
Integer rowSpan = null;
try {
String rowSpanProp = element.getPropertiesMap().getProperty(PROPERTY_TAG_ROWSPAN);
if (rowSpanProp != null) {
rowSpan = Integer.valueOf(rowSpanProp);
}
} catch (NumberFormatException e) {}
if (rowSpan == null) {
try {
String rowSpanProp = element.getPropertiesMap().getProperty(JRCellContents.PROPERTY_ROW_SPAN);
if (rowSpanProp != null) {
rowSpan = Integer.valueOf(rowSpanProp);
}
} catch (NumberFormatException ex) {}
}
if (colSpan != null && colSpan > 1 || rowSpan != null && rowSpan > 1)
{
parentTag.setSpan(colSpan == null ? 0 : colSpan, rowSpan == null ? 0 : rowSpan);
}
}
protected void createListStartTag()
{
PdfStructureEntry listTag = pdfStructure.createTag(tagStack.peek(), "L");
//pdfContentByte.beginMarkedContentSequence(tableTag);
listTag.putArray("K");
tagStack.push(listTag);
}
protected void createListItemStartTag(JRPrintElement element)
{
PdfStructureEntry listItemTag = pdfStructure.createTag(tagStack.peek(), "LI");
//pdfContentByte.beginMarkedContentSequence(tableHeaderTag);
listItemTag.putArray("K");
tagStack.push(listItemTag);
isTagEmpty = true;
}
protected void createEndTags(JRPrintElement element)// throws DocumentException, IOException, JRException
{
if (element.hasProperties())
{
createEndHeadingTags(element, PROPERTY_TAG_H6, AccessibilityTagEnum.H6);
createEndHeadingTags(element, PROPERTY_TAG_H5, AccessibilityTagEnum.H5);
createEndHeadingTags(element, PROPERTY_TAG_H4, AccessibilityTagEnum.H4);
createEndHeadingTags(element, PROPERTY_TAG_H3, AccessibilityTagEnum.H3);
createEndHeadingTags(element, PROPERTY_TAG_H2, AccessibilityTagEnum.H2);
createEndHeadingTags(element, PROPERTY_TAG_H1, AccessibilityTagEnum.H1);
String prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_LI);
if (TAG_END.equals(prop) || TAG_FULL.equals(prop))
{
//pdfContentByte.endMarkedContentSequence();
if (isTagEmpty)
{
pdfStructure.beginTag(tagStack.peek(), "Span");
pdfStructure.endTag();
}
tagStack.pop();
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_L);
if (TAG_END.equals(prop) || TAG_FULL.equals(prop))
{
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
}
prop = element.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE);
if (
prop != null
&& (JRCellContents.TYPE_CROSSTAB_HEADER.equals(prop)
|| JRCellContents.TYPE_COLUMN_HEADER.equals(prop)
|| JRCellContents.TYPE_ROW_HEADER.equals(prop)
|| JRCellContents.TYPE_DATA.equals(prop)))
{
//pdfContentByte.endMarkedContentSequence();
if (isTagEmpty)
{
pdfStructure.beginTag(tagStack.peek(), "Span");
pdfStructure.endTag();
}
tagStack.pop();
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TD);
if (TAG_END.equals(prop) || TAG_FULL.equals(prop))
{
//pdfContentByte.endMarkedContentSequence();
if (isTagEmpty)
{
pdfStructure.beginTag(tagStack.peek(), "Span");
pdfStructure.endTag();
}
tagStack.pop();
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TH);
if (TAG_END.equals(prop) || TAG_FULL.equals(prop))
{
//pdfContentByte.endMarkedContentSequence();
if (isTagEmpty)
{
pdfStructure.beginTag(tagStack.peek(), "Span");
pdfStructure.endTag();
}
tagStack.pop();
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TR);
if (TAG_END.equals(prop) || TAG_FULL.equals(prop))
{
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
}
prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TABLE);
if (TAG_END.equals(prop) || TAG_FULL.equals(prop))
{
//pdfContentByte.endMarkedContentSequence();
tagStack.pop();
}
}
// else
// {
// //check to see if this is the first element without tag properties after a table
// if (tagStack.size() > 2) // check to see if we are at least inside a table row (table/tr)
// {
// PdfStructureElement tag = tagStack.peek();
// if (
// PdfName.TABLEROW.equals(tag.get(PdfName.S))
// && PdfName.TABLE.equals(tag.getParent().get(PdfName.S))
// )
// {
// // take out both row and table tags
// tagStack.pop();
// tagStack.pop();
// }
// }
// }
}
protected void createEndHeadingTags(JRPrintElement element, String pdfTagProp, AccessibilityTagEnum accessibilityTag)
{
String accessibilityTagPropValue = element.getPropertiesMap().getProperty(AccessibilityUtil.PROPERTY_ACCESSIBILITY_TAG);
String pdfTagPropValue = element.getPropertiesMap().getProperty(pdfTagProp);
if (
accessibilityTag.getName().equals(accessibilityTagPropValue)
|| TAG_END.equals(pdfTagPropValue) || TAG_FULL.equals(pdfTagPropValue)
)
{
//pdfContentByte.endMarkedContentSequence();
if (isTagEmpty)
{
pdfStructure.beginTag(tagStack.peek(), "Span");
pdfStructure.endTag();
}
tagStack.pop();
}
}
@Override
public void startUl()
{
createListStartTag();
}
@Override
public void endUl()
{
tagStack.pop();
}
@Override
public void startOl(String type, int cutStart)
{
createListStartTag();
}
@Override
public void endOl()
{
tagStack.pop();
}
@Override
public void startLi(boolean noBullet)
{
createListItemStartTag(null);
}
@Override
public void endLi()
{
if (isTagEmpty)
{
pdfStructure.beginTag(tagStack.peek(), "Span");
pdfStructure.endTag();
}
tagStack.pop();
}
protected StyledTextListWriter getListWriter()
{
return isTagged ? this : null;
}
}