Package org.pentaho.reporting.engine.classic.core.modules.output.table.html.helper

Source Code of org.pentaho.reporting.engine.classic.core.modules.output.table.html.helper.AbstractHtmlPrinter

/*
* This program is free software; you can redistribute it and/or modify it under the
*  terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
*  Foundation.
*
*  You should have received a copy of the GNU Lesser General Public License along with this
*  program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
*  or from the Free Software Foundation, Inc.,
*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*  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 Lesser General Public License for more details.
*
*  Copyright (c) 2006 - 2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core.modules.output.table.html.helper;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.text.NumberFormat;

import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.ClassicEngineInfo;
import org.pentaho.reporting.engine.classic.core.ReportAttributeMap;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorMetaData;
import org.pentaho.reporting.engine.classic.core.modules.output.table.base.CellBackground;
import org.pentaho.reporting.engine.classic.core.modules.output.table.base.SlimSheetLayout;
import org.pentaho.reporting.engine.classic.core.modules.output.table.html.HtmlPrinter;
import org.pentaho.reporting.engine.classic.core.modules.output.table.html.HtmlTableModule;
import org.pentaho.reporting.engine.classic.core.modules.output.table.html.URLRewriteException;
import org.pentaho.reporting.engine.classic.core.util.geom.StrictGeomUtility;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.util.MemoryStringReader;
import org.pentaho.reporting.libraries.fonts.encoding.EncodingRegistry;
import org.pentaho.reporting.libraries.repository.ContentIOException;
import org.pentaho.reporting.libraries.repository.ContentItem;
import org.pentaho.reporting.libraries.repository.ContentLocation;
import org.pentaho.reporting.libraries.repository.NameGenerator;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
import org.pentaho.reporting.libraries.xmlns.common.AttributeList;
import org.pentaho.reporting.libraries.xmlns.writer.XmlWriter;
import org.pentaho.reporting.libraries.xmlns.writer.XmlWriterSupport;

@SuppressWarnings("HardCodedStringLiteral")
public abstract class AbstractHtmlPrinter
{
  public static final String XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
  protected static final String[] XHTML_HEADER = {
      "<!DOCTYPE html",
      "     PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"",
      "     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"};

  protected static final StyleBuilder.CSSKeys[] EMPTY_CELL_ATTRNAMES = new StyleBuilder.CSSKeys[]{StyleBuilder.CSSKeys.FONT_SIZE};
  protected static final String[] EMPTY_CELL_ATTRVALS = new String[]{"1pt"};
  private static final String GENERATOR = ClassicEngineInfo.getInstance().getName() + " version "
      + ClassicEngineInfo.getInstance().getVersion();


  private DefaultStyleBuilderFactory styleBuilderFactory;
  private DefaultHtmlContentGenerator contentGenerator;
  private Configuration configuration;
  private ContentItem styleFile;
  private String styleFileUrl;
  private HtmlTagHelper tagHelper;
  private boolean allowRawLinkTargets;

  public AbstractHtmlPrinter(ResourceManager resourceManager)
  {
    if (resourceManager == null)
    {
      throw new NullPointerException("A resource-manager must be given.");
    }

    contentGenerator = new DefaultHtmlContentGenerator(resourceManager);
  }

  protected void initialize(Configuration configuration)
  {
    this.configuration = configuration;

    this.contentGenerator.setCopyExternalImages("true".equals
        (configuration.getConfigProperty(HtmlTableModule.COPY_EXTERNAL_IMAGES)));
    this.allowRawLinkTargets = "true".equals
        (configuration.getConfigProperty(HtmlTableModule.ALLOW_RAW_LINK_TARGETS));

    styleBuilderFactory = new DefaultStyleBuilderFactory();
    styleBuilderFactory.configure(ClassicEngineBoot.getInstance().getGlobalConfig());

    this.tagHelper = new HtmlTagHelper(configuration, styleBuilderFactory);
  }

  public boolean isAllowRawLinkTargets()
  {
    return allowRawLinkTargets;
  }

  public StyleManager getStyleManager()
  {
    return this.tagHelper.getStyleManager();
  }

  public void setStyleManager(final StyleManager styleManager)
  {
    this.tagHelper.setStyleManager(styleManager);
  }

  public HtmlTagHelper getTagHelper()
  {
    return tagHelper;
  }

  public Configuration getConfiguration()
  {
    return configuration;
  }

  public void setDataWriter(final ContentLocation dataLocation,
                            final NameGenerator dataNameGenerator)
  {
    this.contentGenerator.setDataWriter(dataLocation, dataNameGenerator, getContentReWriteService());
  }

  protected abstract ContentUrlReWriteService getContentReWriteService();

  public StyleBuilder getStyleBuilder()
  {
    return tagHelper.getStyleBuilder();
  }

  public DefaultStyleBuilderFactory getStyleBuilderFactory()
  {
    return styleBuilderFactory;
  }

  public DefaultHtmlContentGenerator getContentGenerator()
  {
    return contentGenerator;
  }

  protected ResourceManager getResourceManager()
  {
    return contentGenerator.getResourceManager();
  }

  protected boolean isProportionalColumnWidths()
  {
    return "true".equals(getConfiguration().getConfigProperty(HtmlTableModule.PROPORTIONAL_COLUMN_WIDTHS, "false"));
  }

  protected void writeColumnDeclaration(final SlimSheetLayout sheetLayout,
                                        final XmlWriter xmlWriter)
      throws IOException
  {
    StyleBuilder styleBuilder = getStyleBuilder();
    DefaultStyleBuilderFactory styleBuilderFactory = getStyleBuilderFactory();
    if (sheetLayout == null)
    {
      throw new NullPointerException();
    }

    final int colCount = sheetLayout.getColumnCount();
    final int fullWidth = (int) StrictGeomUtility.toExternalValue(sheetLayout.getMaxWidth());
    final String[] colWidths = new String[colCount];
    final boolean proportionalColumnWidths = isProportionalColumnWidths();
    final NumberFormat pointConverter = styleBuilder.getPointConverter();
    final String unit;

    if (proportionalColumnWidths)
    {
      unit = "%";

      double totalWidth = 0;
      for (int col = 0; col < colCount; col++)
      {
        final int width = (int) StrictGeomUtility.toExternalValue(sheetLayout.getCellWidth(col, col + 1));
        final double colWidth = styleBuilderFactory.fixLengthForSafari(Math.max(1, width * 100.0d / fullWidth));
        if (col == colCount - 1)
        {
          colWidths[col] = pointConverter.format(100 - totalWidth);
        }
        else
        {
          totalWidth += colWidth;
          colWidths[col] = pointConverter.format(colWidth);
        }
      }
    }
    else
    {
      unit = "pt";

      double totalWidth = 0;
      for (int col = 0; col < colCount; col++)
      {
        final int width = (int) StrictGeomUtility.toExternalValue(sheetLayout.getCellWidth(col, col + 1));
        final double colWidth = styleBuilderFactory.fixLengthForSafari(Math.max(1, width));
        if (col == colCount - 1)
        {
          colWidths[col] = pointConverter.format(fullWidth - totalWidth);
        }
        else
        {
          totalWidth += colWidth;
          colWidths[col] = pointConverter.format(colWidth);
        }
      }
    }

    for (int col = 0; col < colCount; col++)
    {
      // Print the table.
      styleBuilder.clear();
      styleBuilder.append(DefaultStyleBuilder.CSSKeys.WIDTH, colWidths[col], unit);
      xmlWriter.writeTag(null, "col", "style", styleBuilder.toString(), XmlWriterSupport.CLOSE);
    }
  }


  protected void writeCompleteHeader(final XmlWriter docWriter,
                                     final String sheetName,
                                     final ReportAttributeMap attributes,
                                     final String styleSheetUrl,
                                     final StyleManager inlineStyleSheet) throws IOException
  {
    Configuration configuration = getConfiguration();
    final String encoding = configuration.getConfigProperty
        (HtmlTableModule.ENCODING, EncodingRegistry.getPlatformDefaultEncoding());

    docWriter.writeXmlDeclaration(encoding);
    for (int i = 0; i < XHTML_HEADER.length; i++)
    {
      docWriter.writeText(XHTML_HEADER[i]);
      docWriter.writeNewLine();
    }
    docWriter.writeTag(XHTML_NAMESPACE, "html", XmlWriterSupport.OPEN);
    docWriter.writeTag(XHTML_NAMESPACE, "head", XmlWriterSupport.OPEN);

    final String title = configuration.getConfigProperty(HtmlTableModule.TITLE);
    if (title != null)
    {
      docWriter.writeTag(XHTML_NAMESPACE, "title", XmlWriterSupport.OPEN);
      docWriter.writeTextNormalized(title, false);
      docWriter.writeCloseTag();
    }
    // if no single title defined, use the sheetname function previously computed
    else if (sheetName != null)
    {
      docWriter.writeTag(XHTML_NAMESPACE, "title", XmlWriterSupport.OPEN);
      docWriter.writeTextNormalized(sheetName, true);
      docWriter.writeCloseTag();
    }
    else
    {
      docWriter.writeTag(XHTML_NAMESPACE, "title", XmlWriterSupport.OPEN);
      docWriter.writeText(" ");
      docWriter.writeCloseTag();
    }

    writeMeta(docWriter, "subject",
        configuration.getConfigProperty(HtmlTableModule.SUBJECT));
    writeMeta(docWriter, "author",
        configuration.getConfigProperty(HtmlTableModule.AUTHOR));
    writeMeta(docWriter, "keywords",
        configuration.getConfigProperty(HtmlTableModule.KEYWORDS));
    writeMeta(docWriter, "generator", GENERATOR);

    final AttributeList metaAttrs = new AttributeList();
    metaAttrs.setAttribute(XHTML_NAMESPACE, "http-equiv", "content-type");
    metaAttrs.setAttribute(XHTML_NAMESPACE, "content", "text/html; charset=" + encoding);
    docWriter.writeTag(XHTML_NAMESPACE, "meta", metaAttrs, XmlWriterSupport.CLOSE);

    if (styleSheetUrl != null)
    {
      final AttributeList attrList = new AttributeList();
      attrList.setAttribute(XHTML_NAMESPACE, "type", "text/css");
      attrList.setAttribute(XHTML_NAMESPACE, "rel", "stylesheet");
      attrList.setAttribute(XHTML_NAMESPACE, "href", styleSheetUrl);

      docWriter.writeTag(XHTML_NAMESPACE, "link", attrList, XmlWriterSupport.CLOSE);
    }
    else if (inlineStyleSheet != null)
    {
      docWriter.writeTag(XHTML_NAMESPACE, "style", "type", "text/css", XmlWriterSupport.OPEN);
      StringWriter writer = new StringWriter();
      inlineStyleSheet.write(writer);
      docWriter.writeText(writer.toString());
      docWriter.writeCloseTag();
    }

    final Object rawHeaderContent = attributes.getAttribute
        (AttributeNames.Html.NAMESPACE, AttributeNames.Html.EXTRA_RAW_HEADER_CONTENT);
    if (rawHeaderContent != null)
    {
      // Warning: This text is not escaped or processed in any way. it is *RAW* content.
      docWriter.writeText(String.valueOf(rawHeaderContent));
    }
    docWriter.writeCloseTag();
  }


  private void writeMeta(final XmlWriter writer, final String name, final String value) throws IOException
  {
    if (value == null)
    {
      return;
    }
    final AttributeList attrList = new AttributeList();
    attrList.setAttribute(XHTML_NAMESPACE, "name", name);
    attrList.setAttribute(XHTML_NAMESPACE, "content", value);
    writer.writeTag(XHTML_NAMESPACE, "meta", attrList, XmlWriterSupport.CLOSE);
  }

  protected StyleManager createStyleManager()
  {
    if (isCreateBodyFragment() == false && isInlineStylesRequested() == false)
    {
      return new GlobalStyleManager();
    }

    return new InlineStyleManager();
  }

  protected boolean isCreateBodyFragment()
  {
    return "true".equals(getConfiguration().getConfigProperty(HtmlTableModule.BODY_FRAGMENT, "false"));
  }

  protected boolean isInlineStylesRequested()
  {
    return "true".equals(getConfiguration().getConfigProperty(HtmlTableModule.INLINE_STYLE));
  }


  protected void generateHeaderOnOpen(final ReportAttributeMap attributeMap,
                                      final String sheetName,
                                      final XmlWriter xmlWriter) throws IOException
  {
    if (isCreateBodyFragment() == false)
    {
      if (isInlineStylesRequested())
      {
        writeCompleteHeader(xmlWriter, sheetName, attributeMap, null, null);
      }
      else
      {
        if (isExternalStyleSheetRequested())
        {
          if (isForceBufferedWriting() == false)
          {
            writeCompleteHeader(xmlWriter, sheetName, attributeMap, styleFileUrl, null);
          }
        }
      }
      xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "body", XmlWriterSupport.OPEN);
    }
  }

  protected void generateExternalStylePlaceHolder() throws ContentIOException, URLRewriteException
  {
    if (isExternalStyleSheetRequested() == false)
    {
      return;
    }

    this.styleFile = getContentGenerator().createItem("style", "text/css");
    this.styleFileUrl = getContentReWriteService().rewriteContentDataItem(styleFile);
  }

  public ContentItem getStyleFile()
  {
    return styleFile;
  }

  public String getStyleFileUrl()
  {
    return styleFileUrl;
  }

  protected WriterService createWriterService(final OutputStream out) throws UnsupportedEncodingException
  {
    final String encoding = configuration.getConfigProperty
        (HtmlTableModule.ENCODING, EncodingRegistry.getPlatformDefaultEncoding());

    if (isCreateBodyFragment() == false)
    {
      if (isInlineStylesRequested())
      {
        return WriterService.createPassThroughService(out, encoding);
      }
      else
      {
        if (isExternalStyleSheetRequested() && isForceBufferedWriting() == false)
        {
          return WriterService.createPassThroughService(out, encoding);
        }
        else
        {
          return WriterService.createBufferedService(out, encoding);
        }
      }
    }
    else
    {
      return WriterService.createPassThroughService(out, encoding);
    }
  }


  protected boolean isForceBufferedWriting()
  {
    return "true".equals(getConfiguration().getConfigProperty(HtmlTableModule.FORCE_BUFFER_WRITING));
  }

  protected boolean isExternalStyleSheetRequested()
  {
    if (isCreateBodyFragment())
    {
      // body-fragments have no header ..
      return false;
    }

    // We will add the style-declarations directly to the HTML elements ..
    if (isInlineStylesRequested())
    {
      return false;
    }

    // Without the ability to create external files, we cannot create external stylesheet.
    if (getContentGenerator().isExternalContentAvailable() == false)
    {
      return false;
    }

    // User explicitly requested internal styles by disabling the external-style property.
    return "true".equals(getConfiguration().getConfigProperty(HtmlTableModule.EXTERNALIZE_STYLE, "true"));

  }

  protected void performCloseFile(final String sheetName,
                                final ReportAttributeMap logicalPageBox,
                                final WriterService writer)
      throws IOException, ContentIOException
  {
    XmlWriter xmlWriter = writer.getXmlWriter();
    xmlWriter.writeCloseTag(); // for the opening table ..

    final Object rawFooterContent = logicalPageBox.getAttribute(AttributeNames.Html.NAMESPACE,
        AttributeNames.Html.EXTRA_RAW_FOOTER_CONTENT);
    if (rawFooterContent != null)
    {
      xmlWriter.writeText(String.valueOf(rawFooterContent));
    }

    if (isCreateBodyFragment())
    {
      xmlWriter.close();
      return;
    }

    ContentItem styleFile = getStyleFile();
    if (styleFile != null)
    {
      final String encoding = getConfiguration().getConfigProperty
          (HtmlTableModule.ENCODING, EncodingRegistry.getPlatformDefaultEncoding());
      final Writer styleOut = new OutputStreamWriter
          (new BufferedOutputStream(styleFile.getOutputStream()), encoding);
      getStyleManager().write(styleOut);
      styleOut.flush();
      styleOut.close();

      if (isForceBufferedWriting() == false)
      {
        // A complete header had been written when the processing started ..
        xmlWriter.writeCloseTag(); // for the body tag
        xmlWriter.writeCloseTag(); // for the HTML tag
        xmlWriter.close();
        return;
      }
    }
    if (isInlineStylesRequested())
    {
      xmlWriter.writeCloseTag(); // for the body tag
      xmlWriter.writeCloseTag(); // for the HTML tag
      xmlWriter.close();
      return;
    }

    // handle external stylesheets. They need to be injected into the header.

    // finish the body fragment
    xmlWriter.writeCloseTag(); // for the body ..
    xmlWriter.flush();

    final XmlWriter docWriter = writer.createHeaderXmlWriter();
    if (styleFile != null)
    {
      // now its time to write the header with the link to the style-sheet-file
      writeCompleteHeader(docWriter, sheetName, logicalPageBox, getStyleFileUrl(), null);
    }
    else
    {
      writeCompleteHeader(docWriter, sheetName, logicalPageBox, null, getStyleManager());
    }

    // no need to check for IOExceptions here, as we know the implementation does not create such things
    final MemoryStringReader stringReader = writer.getBufferWriter().createReader();
    docWriter.writeStream(stringReader);
    stringReader.close();

    docWriter.writeCloseTag(); // for the html ..
    docWriter.close();
  }

  protected void openSheet(final ReportAttributeMap logicalPage,
                         final String sheetName,
                         final OutputProcessorMetaData metaData,
                         final SlimSheetLayout sheetLayout,
                         final XmlWriter xmlWriter) throws ContentIOException, URLRewriteException, IOException
  {
    setStyleManager(createStyleManager());

    generateExternalStylePlaceHolder();
    generateHeaderOnOpen(logicalPage, sheetName, xmlWriter);

    final Object rawContent = logicalPage.getAttribute(AttributeNames.Html.NAMESPACE,
        AttributeNames.Html.EXTRA_RAW_CONTENT);
    if (rawContent != null)
    {
      xmlWriter.writeText(String.valueOf(rawContent));
    }

    // table name
    if ("true".equals(metaData.getConfiguration().getConfigProperty
        ("org.pentaho.reporting.engine.classic.core.modules.output.table.html.EnableSheetNameProcessing")))
    {
      if (sheetName != null)
      {
        xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "h1", getTagHelper().createSheetNameAttributes(), XmlWriterSupport.OPEN);
        xmlWriter.writeTextNormalized(sheetName, true);
        xmlWriter.writeCloseTag();
      }
    }

    // table
    xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "table",
        getTagHelper().createTableAttributes(sheetLayout, logicalPage),
        XmlWriterSupport.OPEN);
    writeColumnDeclaration(sheetLayout, xmlWriter);
  }

  protected void writeBackgroundCell(CellBackground background, XmlWriter xmlWriter) throws IOException
  {
    final boolean emptyCellsUseCSS = getTagHelper().isEmptyCellsUseCSS();
    if (background == null)
    {
      if (emptyCellsUseCSS)
      {
        xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "td", XmlWriterSupport.CLOSE);
      }
      else
      {
        final AttributeList attrs = new AttributeList();
        attrs.setAttribute(HtmlPrinter.XHTML_NAMESPACE, "style", "font-size: 1pt");
        xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "td", attrs, XmlWriterSupport.OPEN);
        xmlWriter.writeText("&nbsp;");
        xmlWriter.writeCloseTag();
      }
      return;
    }

    StyleBuilder styleBuilder = getStyleBuilder();
    DefaultStyleBuilderFactory styleBuilderFactory = getStyleBuilderFactory();

    // Background cannot be null at this point ..
    final String[] anchor = background.getAnchors();
    if (anchor.length == 0 && emptyCellsUseCSS)
    {
      final StyleBuilder cellStyle = styleBuilderFactory.createCellStyle(styleBuilder, null, null, background, null, null);
      final AttributeList cellAttributes = getTagHelper().createCellAttributes(1, 1, null, null, background, cellStyle);
      xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "td", cellAttributes, XmlWriterSupport.CLOSE);
    }
    else
    {
      final StyleBuilder cellStyle = styleBuilderFactory.createCellStyle
          (styleBuilder, null, null, background, HtmlPrinter.EMPTY_CELL_ATTRNAMES, HtmlPrinter.EMPTY_CELL_ATTRVALS);
      final AttributeList cellAttributes = getTagHelper().createCellAttributes(1, 1, null, null, background, cellStyle);
      xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "td", cellAttributes, XmlWriterSupport.OPEN);
      for (int i = 0; i < anchor.length; i++)
      {
        xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "a", "name", anchor[i], XmlWriterSupport.CLOSE);
      }
      xmlWriter.writeText("&nbsp;");
      xmlWriter.writeCloseTag();

    }

  }

}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.modules.output.table.html.helper.AbstractHtmlPrinter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.