Package org.pentaho.reporting.designer.core.editor.crosstab

Source Code of org.pentaho.reporting.designer.core.editor.crosstab.CrosstabEditSupport$DetailsDefinition

/*
* 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 - 2009 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.reporting.designer.core.editor.crosstab;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;

import org.pentaho.reporting.designer.core.editor.ReportDocumentContext;
import org.pentaho.reporting.designer.core.model.ModelUtility;
import org.pentaho.reporting.designer.core.util.undo.UndoEntry;
import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition;
import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.Band;
import org.pentaho.reporting.engine.classic.core.CrosstabCell;
import org.pentaho.reporting.engine.classic.core.CrosstabCellBody;
import org.pentaho.reporting.engine.classic.core.CrosstabColumnGroup;
import org.pentaho.reporting.engine.classic.core.CrosstabGroup;
import org.pentaho.reporting.engine.classic.core.CrosstabOtherGroup;
import org.pentaho.reporting.engine.classic.core.CrosstabRowGroup;
import org.pentaho.reporting.engine.classic.core.DetailsHeader;
import org.pentaho.reporting.engine.classic.core.Element;
import org.pentaho.reporting.engine.classic.core.Group;
import org.pentaho.reporting.engine.classic.core.GroupBody;
import org.pentaho.reporting.engine.classic.core.GroupDataBody;
import org.pentaho.reporting.engine.classic.core.RelationalGroup;
import org.pentaho.reporting.engine.classic.core.ReportElement;
import org.pentaho.reporting.engine.classic.core.SubGroupBody;
import org.pentaho.reporting.engine.classic.core.dom.AndMatcher;
import org.pentaho.reporting.engine.classic.core.dom.AttributeMatcher;
import org.pentaho.reporting.engine.classic.core.dom.ElementMatcher;
import org.pentaho.reporting.engine.classic.core.dom.MatcherContext;
import org.pentaho.reporting.engine.classic.core.dom.NodeMatcher;
import org.pentaho.reporting.engine.classic.core.dom.ReportStructureMatcher;
import org.pentaho.reporting.engine.classic.core.elementfactory.CrosstabBuilder;
import org.pentaho.reporting.engine.classic.core.elementfactory.CrosstabDetail;
import org.pentaho.reporting.engine.classic.core.elementfactory.CrosstabDimension;
import org.pentaho.reporting.engine.classic.core.filter.types.LabelType;
import org.pentaho.reporting.engine.classic.core.function.AggregationFunction;
import org.pentaho.reporting.engine.classic.core.util.InstanceID;
import org.pentaho.reporting.engine.classic.core.wizard.ContextAwareDataSchemaModel;
import org.pentaho.reporting.libraries.base.util.ArgumentNullException;

public final class CrosstabEditSupport
{
  public static class EditGroupOnReportUndoEntry implements UndoEntry
  {
    private static final long serialVersionUID = -6048384734272767240L;
    private Group newRootGroup;
    private Group oldRootGroup;

    public EditGroupOnReportUndoEntry(final Group oldRootGroup, final Group newRootGroup)
    {
      this.oldRootGroup = oldRootGroup.derive(true);
      this.newRootGroup = newRootGroup.derive(true);
    }

    public void undo(final ReportDocumentContext renderContext)
    {
      final AbstractReportDefinition report = renderContext.getReportDefinition();
      report.setRootGroup(oldRootGroup.derive(true));
    }

    public void redo(final ReportDocumentContext renderContext)
    {
      final AbstractReportDefinition report = renderContext.getReportDefinition();
      report.setRootGroup(newRootGroup.derive(true));
    }

    public UndoEntry merge(final UndoEntry newEntry)
    {
      return null;
    }
  }

  public static class EditGroupOnGroupUndoEntry implements UndoEntry
  {
    private InstanceID target;
    private Group newRootGroup;
    private Group oldRootGroup;

    public EditGroupOnGroupUndoEntry(final InstanceID target,
                                     final Group oldRootGroup,
                                     final Group newRootGroup)
    {
      ArgumentNullException.validate("target", target);
      ArgumentNullException.validate("oldRootGroup", oldRootGroup);
      ArgumentNullException.validate("newRootGroup", newRootGroup);

      this.target = target;
      this.oldRootGroup = oldRootGroup.derive(true);
      this.newRootGroup = newRootGroup.derive(true);
    }

    public void undo(final ReportDocumentContext renderContext)
    {
      final SubGroupBody bodyElement = (SubGroupBody)
          ModelUtility.findElementById(renderContext.getReportDefinition(), target);
      if (bodyElement == null)
      {
        throw new IllegalStateException("Expected to find a sub-group-body on the specified ID.");
      }

      bodyElement.setGroup(oldRootGroup.derive(true));
    }

    public void redo(final ReportDocumentContext renderContext)
    {
      final SubGroupBody bodyElement = (SubGroupBody)
          ModelUtility.findElementById(renderContext.getReportDefinition(), target);

      if (bodyElement == null)
      {
        throw new IllegalStateException("Expected to find a sub-group-body on this report.");
      }

      bodyElement.setGroup(newRootGroup.derive(true));
    }

    public UndoEntry merge(final UndoEntry newEntry)
    {
      return null;
    }
  }

  public static class DetailsDefinition
  {
    private Element labelElement;
    private Element detailElement;
    private String field;
    private Class<AggregationFunction> aggregationFunction;

    private DetailsDefinition(final Element labelElement,
                              final Element detailElement,
                              final String field,
                              final Class<AggregationFunction> aggregationFunction)
    {
      this.labelElement = labelElement;
      this.detailElement = detailElement;
      this.field = field;
      this.aggregationFunction = aggregationFunction;
    }

    public Element getLabelElement()
    {
      return labelElement;
    }

    public Element getDetailElement()
    {
      return detailElement;
    }

    public String getField()
    {
      return field;
    }

    public Class<AggregationFunction> getAggregationFunction()
    {
      return aggregationFunction;
    }

    public CrosstabDetail createDetail()
    {
      final String label = (String) labelElement.getAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE);
      return new CrosstabDetail(field, label, aggregationFunction);
    }
  }

  private CrosstabEditSupport()
  {
  }

  public static GroupDataBody installCrosstabIntoLastGroup(final RelationalGroup selectedGroup,
                                                           final CrosstabGroup newGroup)
  {
    final GroupDataBody oldBody = (GroupDataBody) selectedGroup.getBody();
    // install the new crosstab group into the group
    selectedGroup.setBody(new SubGroupBody(newGroup));
    return oldBody;
  }

  private static void populateOptions(final LinkedHashMap<String, DetailsDefinition> cellBody,
                                      final CrosstabBuilder builder)
  {
    builder.setMaximumHeight(null);
    builder.setMaximumWidth(null);
    builder.setPrefHeight(null);
    builder.setPrefWidth(null);
    builder.setMinimumHeight(new Float(-100));
    builder.setMinimumWidth(new Float(-100));

    Collection<DetailsDefinition> values = cellBody.values();
    Boolean allowMetaAttrs = null;
    Boolean allowMetaStyle = null;

    for (final DetailsDefinition value : values)
    {
      Element detailElement = value.getDetailElement();
      if (detailElement != null)
      {
        if (allowMetaAttrs == null)
        {
          allowMetaAttrs = detailElement.getAttributeTyped
              (AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES, Boolean.class);
        }

        if (allowMetaStyle == null)
        {
          allowMetaStyle = detailElement.getAttributeTyped
              (AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING, Boolean.class);
        }
      }
    }

    builder.setAllowMetaDataAttributes(allowMetaAttrs);
    builder.setAllowMetaDataStyling(allowMetaStyle);

    // todo: v2 - try to restore the active settings for width and heights
  }

  public static CrosstabBuilder populateBuilder(final CrosstabGroup editedGroup,
                                                final ContextAwareDataSchemaModel reportDataSchemaModel)
  {
    CrosstabCellBody cellBody = null;
    Group group = editedGroup.getBody().getGroup();

    ArrayList<CrosstabRowGroup> rows = new ArrayList<CrosstabRowGroup>();
    ArrayList<CrosstabColumnGroup> cols = new ArrayList<CrosstabColumnGroup>();
    ArrayList<CrosstabOtherGroup> others = new ArrayList<CrosstabOtherGroup>();

    while (group != null)
    {
      if (group instanceof CrosstabOtherGroup)
      {
        CrosstabOtherGroup otherGroup = (CrosstabOtherGroup) group;
        others.add(otherGroup);
      }
      else if (group instanceof CrosstabRowGroup)
      {
        CrosstabRowGroup rowGroup = (CrosstabRowGroup) group;
        rows.add(rowGroup);
      }
      else if (group instanceof CrosstabColumnGroup)
      {
        CrosstabColumnGroup colGroup = (CrosstabColumnGroup) group;
        cols.add(colGroup);
      }
      else
      {
        break;
      }

      GroupBody body = group.getBody();
      if (body instanceof CrosstabCellBody)
      {
        cellBody = (CrosstabCellBody) body;
        break;
      }

      group = body.getGroup();
    }

    if (cellBody == null)
    {
      throw new IllegalStateException("A crosstab group can never be without a cell body");
    }

    LinkedHashMap<String, DetailsDefinition> details;
    CrosstabCell element = cellBody.findElement(null, null);
    if (element != null)
    {
      details = extractFromDetailCell(element, cellBody.getHeader());
    }
    else
    {
      details = new LinkedHashMap<String, DetailsDefinition>();
    }

    final CrosstabEditorBuilder builder = new CrosstabEditorBuilder(reportDataSchemaModel, cellBody, details);
    populateOptions(details, builder);
    for (final CrosstabOtherGroup other : others)
    {
      builder.addOtherDimension(other);
    }
    for (final CrosstabRowGroup row : rows)
    {
      builder.addRowDimension(extractFromRowGroup(row), row);
    }
    for (final CrosstabColumnGroup col : cols)
    {
      builder.addColumnDimension(extractFromColumnGroup(col), col);
    }
    for (final DetailsDefinition value : details.values())
    {
      builder.addDetails(value.createDetail());
    }
    return builder;
  }

  private static LinkedHashMap<String, DetailsDefinition> extractFromDetailCell(final CrosstabCell cell,
                                                                                final DetailsHeader header)
  {
    ReportElement[] elementsByAttribute =
        ReportStructureMatcher.findElementsByAttribute(cell, AttributeNames.Core.NAMESPACE, AttributeNames.Core.FIELD);
    final LinkedHashMap<String, DetailsDefinition> d = new LinkedHashMap<String, DetailsDefinition>();
    for (final ReportElement e : elementsByAttribute)
    {
      String field = (String) e.getAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.FIELD);
      Class agg = (Class) e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.AGGREGATION_TYPE);
      if (!AggregationFunction.class.isAssignableFrom(agg))
      {
        agg = null;
      }
      ReportElement[] labels = ReportStructureMatcher.findElementsByAttribute
          (header, AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.LABEL_FOR, field);
      Element label;
      if (labels.length > 0)
      {
        label = (Element) labels[0];
      }
      else
      {
        label = null;
      }
      d.put(field, new DetailsDefinition(label, (Element) e, field, agg));
    }
    return d;
  }

  private static CrosstabDimension extractFromRowGroup(final CrosstabRowGroup rowGroup)
  {
    final String title = findTitle(rowGroup.getField(), rowGroup.getTitleHeader());
    final String summaryTitle = findTitle(rowGroup.getField(), rowGroup.getSummaryHeader());
    final boolean summary = rowGroup.isPrintSummary();
    return new CrosstabDimension(rowGroup.getField(), title, summary, summaryTitle);
  }

  private static String findTitle(final String field, final Band titleHeader)
  {
    final MatcherContext context = new MatcherContext();
    context.setMatchSubReportChilds(false);

    NodeMatcher m = new AndMatcher(new ElementMatcher(LabelType.INSTANCE),
        new AttributeMatcher(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.LABEL_FOR, field));
    ReportElement match = ReportStructureMatcher.match(context, titleHeader, m);
    if (match == null)
    {
      if (titleHeader.getElementCount() > 0)
      {
        Element e = titleHeader.getElement(0);
        if (e.getElementType() instanceof LabelType)
        {
          return e.getAttributeTyped(AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, String.class);
        }
      }
      return null;
    }

    return match.getAttributeTyped(AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, String.class);
  }

  private static CrosstabDimension extractFromColumnGroup(final CrosstabColumnGroup rowGroup)
  {
    final String title = findTitle(rowGroup.getField(), rowGroup.getTitleHeader());
    final String summaryTitle = findTitle(rowGroup.getField(), rowGroup.getSummaryHeader());
    final boolean summary = rowGroup.isPrintSummary();
    return new CrosstabDimension(rowGroup.getField(), title, summary, summaryTitle);
  }
}
TOP

Related Classes of org.pentaho.reporting.designer.core.editor.crosstab.CrosstabEditSupport$DetailsDefinition

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.