Package org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.elements

Source Code of org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.elements.AbstractElementWriteHandler

/*
* 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) 2001 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.elements;

import java.beans.PropertyEditor;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.Element;
import org.pentaho.reporting.engine.classic.core.ParameterMapping;
import org.pentaho.reporting.engine.classic.core.ReportElement;
import org.pentaho.reporting.engine.classic.core.RootLevelBand;
import org.pentaho.reporting.engine.classic.core.Section;
import org.pentaho.reporting.engine.classic.core.SubReport;
import org.pentaho.reporting.engine.classic.core.function.Expression;
import org.pentaho.reporting.engine.classic.core.metadata.AttributeMetaData;
import org.pentaho.reporting.engine.classic.core.metadata.ElementMetaData;
import org.pentaho.reporting.engine.classic.core.metadata.ElementType;
import org.pentaho.reporting.engine.classic.core.metadata.ElementTypeRegistry;
import org.pentaho.reporting.engine.classic.core.metadata.ResourceReference;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.BundleNamespaces;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.BundleElementWriteHandler;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.BundleElementWriterFactory;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.BundleWriterException;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.BundleWriterState;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.ExpressionWriterUtility;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.StyleWriterUtility;
import org.pentaho.reporting.engine.classic.core.style.StyleKey;
import org.pentaho.reporting.engine.classic.core.util.beans.BeanException;
import org.pentaho.reporting.engine.classic.core.util.beans.ConverterRegistry;
import org.pentaho.reporting.libraries.base.util.IOUtils;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.docbundle.BundleUtilities;
import org.pentaho.reporting.libraries.docbundle.DocumentBundle;
import org.pentaho.reporting.libraries.docbundle.WriteableDocumentBundle;
import org.pentaho.reporting.libraries.resourceloader.ResourceException;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
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;

/**
* Provides a base implementation for element write handlers.
*
* @author Thomas Morgner
*/
public abstract class AbstractElementWriteHandler implements BundleElementWriteHandler
{
  private static final Log logger = LogFactory.getLog(AbstractElementWriteHandler.class);

  protected AbstractElementWriteHandler()
  {
  }

  protected void copyStaticResources(final WriteableDocumentBundle bundle,
                                     final BundleWriterState state,
                                     final Element element) throws BundleWriterException
  {
    if (bundle == null)
    {
      throw new NullPointerException();
    }
    if (state == null)
    {
      throw new NullPointerException();
    }
    if (element == null)
    {
      throw new NullPointerException();
    }


    final ResourceKey contentBase = element.getContentBase();
    if (contentBase == null)
    {
      // treat all resources as linked resources ..
      AbstractElementWriteHandler.logger.debug("No content base, treating all content as linked.");
      return;
    }
    final ResourceKey defSource = element.getDefinitionSource();
    if (defSource == null)
    {
      // treat all resources as linked resources ..
      AbstractElementWriteHandler.logger.debug("No report definition source, treating all content as linked.");
      return;
    }

    if (ObjectUtilities.equal(contentBase.getParent(), defSource.getParent()) == false)
    {
      // treat all resources as linked resources ..
      AbstractElementWriteHandler.logger.debug(
          "Content base points to non-bundle location, treating all content as linked.");
      return;
    }

    final Object contentBasePathRaw = contentBase.getIdentifier();
    if (contentBasePathRaw instanceof String == false)
    {
      return;
    }

    final String contentBasePath = String.valueOf(contentBasePathRaw);
    final ResourceManager resourceManager = state.getMasterReport().getResourceManager();

    final ElementType type = element.getElementType();
    final ElementMetaData data = type.getMetaData();
    final AttributeMetaData[] datas = data.getAttributeDescriptions();
    for (int i = 0; i < datas.length; i++)
    {
      final AttributeMetaData attributeMetaData = datas[i];
      if (attributeMetaData.isTransient())
      {
        continue;
      }
      if (isFiltered(attributeMetaData))
      {
        continue;
      }

      final Object attValue = element.getAttribute(attributeMetaData.getNameSpace(), attributeMetaData.getName());
      if (attValue == null)
      {
        continue;
      }
      final ResourceReference[] referencedResources = attributeMetaData.getReferencedResources
          (element, state.getMasterReport().getResourceManager(), attValue);
      for (int j = 0; j < referencedResources.length; j++)
      {
        final ResourceReference reference = referencedResources[j];
        if (reference.isLinked())
        {
          AbstractElementWriteHandler.logger.debug("Linked Resource will not be copied into bundle: " + reference);
          continue;
        }

        final ResourceKey path = reference.getPath();
        final Object identifier = path.getIdentifier();
        if (identifier instanceof String == false)
        {
          AbstractElementWriteHandler.logger.warn("Resource-Bundle-Key has no parseable path: " + path);
          continue;
        }

        final String identifierString = String.valueOf(identifier);
        final String relativePath = IOUtils.getInstance().createRelativePath(identifierString, contentBasePath);
        try
        {
          BundleUtilities.copyInto(bundle, relativePath, path, resourceManager);
        }
        catch (Exception e)
        {
          throw new BundleWriterException("Failed to copy content from key " + path, e);
        }
        AbstractElementWriteHandler.logger.debug("Copied " + path + " as " + relativePath);
      }
    }
  }

  protected boolean isFiltered(final AttributeMetaData attributeMetaData)
  {
    return false;
  }

  protected AttributeList createMainAttributes(final Element element,
                                               final XmlWriter writer)
  {
    return createMainAttributes(element, writer, new AttributeList());
  }

  protected AttributeList createMainAttributes(final Element element,
                                               final XmlWriter writer,
                                               final AttributeList attList)
  {
    if (element == null)
    {
      throw new NullPointerException();
    }
    if (writer == null)
    {
      throw new NullPointerException();
    }
    if (attList == null)
    {
      throw new NullPointerException();
    }

    final ElementMetaData metaData = element.getElementType().getMetaData();
    final String[] attributeNamespaces = element.getAttributeNamespaces();
    for (int i = 0; i < attributeNamespaces.length; i++)
    {
      final String namespace = attributeNamespaces[i];
      final String[] attributeNames = element.getAttributeNames(namespace);
      for (int j = 0; j < attributeNames.length; j++)
      {
        final String name = attributeNames[j];
        final Object value = element.getAttribute(namespace, name);
        if (value == null)
        {
          continue;
        }

        final AttributeMetaData attrMeta = metaData.getAttributeDescription(namespace, name);
        if (attrMeta == null)
        {
          if (value instanceof String)
          {
            ensureNamespaceDefined(writer, attList, namespace);

            // preserve strings, but discard anything else. Until a attribute has a definition, we cannot
            // hope to understand the attribute's value. String-attributes can be expressed in XML easily,
            // and string is also how all unknown attributes are stored by the parser.
            attList.setAttribute(namespace, name, String.valueOf(value));
          }
          continue;
        }

        if (attrMeta.isTransient())
        {
          continue;
        }
        if (isFiltered(attrMeta))
        {
          continue;
        }
        if (attrMeta.isBulk())
        {
          continue;
        }

        ensureNamespaceDefined(writer, attList, namespace);
        try
        {
          final PropertyEditor propertyEditor = attrMeta.getEditor();
          if (propertyEditor != null)
          {
            propertyEditor.setValue(value);
            attList.setAttribute(namespace, name, propertyEditor.getAsText());
          }
          else
          {
            final String attrValue = ConverterRegistry.toAttributeValue(value);
            attList.setAttribute(namespace, name, attrValue);
          }

        }
        catch (BeanException e)
        {
          AbstractElementWriteHandler.logger.warn(
              "Attribute '" + namespace + '|' + name + "' is not convertible with the bean-methods");
        }
      }
    }
    return attList;
  }

  private void ensureNamespaceDefined(final XmlWriter writer, final AttributeList attList, final String namespace)
  {
    if (writer.isNamespaceDefined(namespace) == false &&
        attList.isNamespaceUriDefined(namespace) == false)
    {
      final String prefix = ElementTypeRegistry.getInstance().getNamespacePrefix(namespace);
      if (prefix != null)
      {
        if (writer.isNamespacePrefixDefined(prefix) == false)
        {
          attList.addNamespaceDeclaration(prefix, namespace);
          return;
        }
      }

      attList.addNamespaceDeclaration("autoGenNs", namespace);
    }
  }

  protected void writeElementBody(final WriteableDocumentBundle bundle,
                                  final BundleWriterState state,
                                  final Element element, final XmlWriter writer)
      throws IOException, BundleWriterException
  {
    if (bundle == null)
    {
      throw new NullPointerException();
    }
    if (state == null)
    {
      throw new NullPointerException();
    }
    if (element == null)
    {
      throw new NullPointerException();
    }
    if (writer == null)
    {
      throw new NullPointerException();
    }

    StyleWriterUtility.writeStyleRule(BundleNamespaces.STYLE, "element-style", writer, element.getStyle(), false);
    writeStyleExpressions(bundle, state, element, writer);
    writeBulkAttributes(bundle, state, element, writer);
    writeAttributeExpressions(bundle, state, element, writer);
  }

  private void writeBulkAttributes(final WriteableDocumentBundle bundle,
                                   final BundleWriterState state,
                                   final Element element,
                                   final XmlWriter writer) throws IOException,BundleWriterException
  {
    final ElementMetaData metaData = element.getElementType().getMetaData();
    final String[] attributeNamespaces = element.getAttributeNamespaces();
    for (int i = 0; i < attributeNamespaces.length; i++)
    {
      final String namespace = attributeNamespaces[i];
      final String[] attributeNames = element.getAttributeNames(namespace);
      for (int j = 0; j < attributeNames.length; j++)
      {
        final String name = attributeNames[j];
        final Object value = element.getAttribute(namespace, name);
        if (value == null)
        {
          continue;
        }

        final AttributeMetaData attrMeta = metaData.getAttributeDescription(namespace, name);
        if (attrMeta == null)
        {
          continue;
        }

        if (attrMeta.isTransient())
        {
          continue;
        }
        if (isFiltered(attrMeta))
        {
          continue;
        }
        if (attrMeta.isBulk() == false)
        {
          continue;
        }

        if ("Resource".equals(attrMeta.getValueRole()))
        {
          final AttributeList attList = new AttributeList();
          if (attList.isNamespaceUriDefined(namespace) == false &&
              writer.isNamespaceDefined(namespace) == false)
          {
            attList.addNamespaceDeclaration("autoGenNS", namespace);
          }

          if (value instanceof URL)
          {
            attList.setAttribute(AttributeNames.Core.NAMESPACE, "resource-type", "url");
            writer.writeTag(namespace, attrMeta.getName(), attList, XmlWriter.OPEN);
            writer.writeTextNormalized(String.valueOf(value), true);
            writer.writeCloseTag();
          }
          else if (value instanceof ResourceKey)
          {
            try
            {
              final ResourceKey key = (ResourceKey) value;
              final ResourceManager resourceManager = bundle.getResourceManager();
              final ResourceKey bundleKey = bundle.getBundleKey().getParent();
              final String serializedKey = resourceManager.serialize(bundleKey, key);
              attList.setAttribute(AttributeNames.Core.NAMESPACE, "resource-type", "resource-key");
              writer.writeTag(namespace, attrMeta.getName(), attList, XmlWriter.OPEN);
              writer.writeTextNormalized(serializedKey, true);
              writer.writeCloseTag();
            }
            catch (ResourceException re)
            {
              logger.error("Could not serialize the ResourceKey: " + re.getMessage(), re);
              throw new IOException("Could not serialize the ResourceKey: " + re.getMessage());
            }
          }
          else if (value instanceof File)
          {
            attList.setAttribute(AttributeNames.Core.NAMESPACE, "resource-type", "file");
            writer.writeTag(namespace, attrMeta.getName(), attList, XmlWriter.OPEN);
            writer.writeTextNormalized(String.valueOf(value), true);
            writer.writeCloseTag();
          }
          else if (value instanceof String)
          {
            attList.setAttribute(AttributeNames.Core.NAMESPACE, "resource-type", "local-ref");
            writer.writeTag(namespace, attrMeta.getName(), attList, XmlWriter.OPEN);
            writer.writeTextNormalized(String.valueOf(value), true);
            writer.writeCloseTag();
          }
          else
          {
            logger.warn("Unknown value-type in resource-attribute " + namespace + ":" + name);
          }

          continue;
        }

        if ("Expression".equals(attrMeta.getValueRole()) && value instanceof Expression)
        {
          // write attribute-expressions.
          final AttributeList attList = new AttributeList();
          attList.setAttribute(BundleNamespaces.LAYOUT, "attribute-namespace", namespace);
          attList.setAttribute(BundleNamespaces.LAYOUT, "attribute-name", name);
          ExpressionWriterUtility.writeExpressionCore
              (bundle, state, (Expression) value, writer, BundleNamespaces.LAYOUT, "expression", attList);
          continue;
        }

        try
        {
          final PropertyEditor propertyEditor = attrMeta.getEditor();
          if (propertyEditor != null)
          {

            propertyEditor.setValue(value);
            final String text = propertyEditor.getAsText();

            final AttributeList attList = new AttributeList();
            if (attList.isNamespaceUriDefined(namespace) == false &&
                writer.isNamespaceDefined(namespace) == false)
            {
              attList.addNamespaceDeclaration("autoGenNS", namespace);
            }
            writer.writeTag(namespace, attrMeta.getName(), attList, XmlWriter.OPEN);
            writer.writeTextNormalized(text, true);
            writer.writeCloseTag();
          }
          else
          {
            final String attrValue = ConverterRegistry.toAttributeValue(value);
            final AttributeList attList = new AttributeList();
            if (attList.isNamespaceUriDefined(namespace) == false &&
                writer.isNamespaceDefined(namespace) == false)
            {
              attList.addNamespaceDeclaration("autoGenNS", namespace);
            }
            writer.writeTag(namespace, attrMeta.getName(), attList, XmlWriter.OPEN);
            writer.writeTextNormalized(attrValue, true);
            writer.writeCloseTag();
          }

        }
        catch (BeanException e)
        {
          AbstractElementWriteHandler.logger.warn(
              "Attribute '" + namespace + '|' + name + "' is not convertible with the bean-methods");
        }
      }
    }
  }

  protected void writeAttributeExpressions(final WriteableDocumentBundle bundle,
                                           final BundleWriterState state,
                                           final Element element, final XmlWriter writer)
      throws IOException, BundleWriterException
  {
    if (bundle == null)
    {
      throw new NullPointerException();
    }
    if (state == null)
    {
      throw new NullPointerException();
    }
    if (element == null)
    {
      throw new NullPointerException();
    }
    if (writer == null)
    {
      throw new NullPointerException();
    }

    // write attribute-expressions.
    final String[] attributeNamespaces = element.getAttributeExpressionNamespaces();
    for (int i = 0; i < attributeNamespaces.length; i++)
    {
      final String namespace = attributeNamespaces[i];
      final String[] attributeNames = element.getAttributeExpressionNames(namespace);
      for (int j = 0; j < attributeNames.length; j++)
      {
        final String name = attributeNames[j];
        final AttributeList attList = new AttributeList();
        attList.setAttribute(BundleNamespaces.LAYOUT, "namespace", namespace);
        attList.setAttribute(BundleNamespaces.LAYOUT, "name", name);
        final Expression ex = element.getAttributeExpression(namespace, name);
        ExpressionWriterUtility.writeExpressionCore
            (bundle, state, ex, writer, BundleNamespaces.LAYOUT, "attribute-expression", attList);
      }
    }
  }

  protected void writeStyleExpressions(final WriteableDocumentBundle bundle,
                                       final BundleWriterState state,
                                       final Element element, final XmlWriter writer)
      throws IOException, BundleWriterException
  {
    if (bundle == null)
    {
      throw new NullPointerException();
    }
    if (state == null)
    {
      throw new NullPointerException();
    }
    if (element == null)
    {
      throw new NullPointerException();
    }
    if (writer == null)
    {
      throw new NullPointerException();
    }

    // write style expressions.
    final Map styleExpressions = element.getStyleExpressions();
    final Iterator styleExpressionsIt = styleExpressions.entrySet().iterator();
    while (styleExpressionsIt.hasNext())
    {
      final Map.Entry entry = (Map.Entry) styleExpressionsIt.next();
      final StyleKey key = (StyleKey) entry.getKey();
      final Expression ex = (Expression) entry.getValue();
      ExpressionWriterUtility.writeStyleExpression(bundle, state, ex, writer, key, BundleNamespaces.LAYOUT,
          "style-expression");
    }
  }

  protected void writeChildElements(final WriteableDocumentBundle bundle,
                                    final BundleWriterState state,
                                    final XmlWriter xmlWriter,
                                    final Section section) throws IOException, BundleWriterException
  {
    if (bundle == null)
    {
      throw new NullPointerException();
    }
    if (state == null)
    {
      throw new NullPointerException();
    }
    if (xmlWriter == null)
    {
      throw new NullPointerException();
    }
    if (section == null)
    {
      throw new NullPointerException();
    }

    final int count = section.getElementCount();
    for (int i = 0; i < count; i++)
    {
      final ReportElement re = section.getElement(i);
      if (re instanceof Element == false)
      {
        throw new IllegalStateException("Cannot write custom implementations of report-element.");
      }
      final Element e = (Element) re;
      final BundleElementWriteHandler writeHandler = BundleElementWriterFactory.createHandler(e);
      writeHandler.writeElement(bundle, state, xmlWriter, e);
    }
  }

  protected void writeRootSubReports(final WriteableDocumentBundle bundle,
                                     final BundleWriterState state,
                                     final XmlWriter xmlWriter,
                                     final RootLevelBand rootLevelBand) throws IOException, BundleWriterException
  {
    if (bundle == null)
    {
      throw new NullPointerException();
    }
    if (state == null)
    {
      throw new NullPointerException();
    }
    if (xmlWriter == null)
    {
      throw new NullPointerException();
    }
    if (rootLevelBand == null)
    {
      throw new NullPointerException();
    }

    final SubReport[] reports = rootLevelBand.getSubReports();
    for (int i = 0; i < reports.length; i++)
    {
      writeSubReport(bundle, state, xmlWriter, reports[i]);
    }
  }

  protected void writeSubReport(final WriteableDocumentBundle bundle,
                                final BundleWriterState state,
                                final XmlWriter xmlWriter,
                                final SubReport subReport) throws IOException, BundleWriterException
  {
    if (bundle == null)
    {
      throw new NullPointerException();
    }
    if (state == null)
    {
      throw new NullPointerException();
    }
    if (xmlWriter == null)
    {
      throw new NullPointerException();
    }
    if (subReport == null)
    {
      throw new NullPointerException();
    }

    final String absolutePath = computePath(state);
    final String directory = BundleUtilities.getUniqueName(bundle, absolutePath + "/subreport{0}");
    bundle.createDirectoryEntry(directory, "application/vnd.pentaho.reporting.classic.subreport");
    final String dirRelative = IOUtils.getInstance().createRelativePath(directory, absolutePath + "/.");
    final BundleWriterState subReportState = new BundleWriterState(state, subReport, dirRelative + '/');
    state.getBundleWriter().writeSubReport(bundle, subReportState);

    final ParameterMapping[] inputMappings = subReport.getInputMappings();
    final ParameterMapping[] outputMappings = subReport.getExportMappings();
    final String tagName = subReport.getElementTypeName();
    if (inputMappings.length == 0 && outputMappings.length == 0)
    {
      xmlWriter.writeTag(BundleNamespaces.LAYOUT, tagName, "href",
          '/' + subReportState.getFileName() + "content.xml", XmlWriterSupport.CLOSE);
    }
    else
    {
      xmlWriter.writeTag(BundleNamespaces.LAYOUT, tagName, "href",
          '/' + subReportState.getFileName() + "content.xml", XmlWriterSupport.OPEN);

      for (int i = 0; i < inputMappings.length; i++)
      {
        final ParameterMapping mapping = inputMappings[i];
        final AttributeList attrs = new AttributeList();
        attrs.setAttribute(BundleNamespaces.LAYOUT, "master-fieldname", mapping.getName());
        attrs.setAttribute(BundleNamespaces.LAYOUT, "detail-fieldname", mapping.getAlias());
        xmlWriter.writeTag(BundleNamespaces.LAYOUT, "input-parameter", attrs, XmlWriterSupport.CLOSE);
      }

      for (int i = 0; i < outputMappings.length; i++)
      {
        final ParameterMapping mapping = outputMappings[i];
        final AttributeList attrs = new AttributeList();
        attrs.setAttribute(BundleNamespaces.LAYOUT, "master-fieldname", mapping.getName());
        attrs.setAttribute(BundleNamespaces.LAYOUT, "detail-fieldname", mapping.getAlias());
        xmlWriter.writeTag(BundleNamespaces.LAYOUT, "output-parameter", attrs, XmlWriterSupport.CLOSE);
      }
      xmlWriter.writeCloseTag();
    }
  }

  private String computePath(final BundleWriterState state)
  {
    final String absolutePathWithDummy = IOUtils.getInstance().getAbsolutePath("dummy", state.getFileName());
    final String absolutePath = absolutePathWithDummy.substring(0, absolutePathWithDummy.length() - "dummy".length());
    if (absolutePath.endsWith("/"))
    {
      return absolutePath.substring(0, absolutePath.length() - 1);
    }
    return absolutePath;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.elements.AbstractElementWriteHandler

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.