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

Source Code of org.pentaho.reporting.designer.core.editor.attributes.AbstractAttributeTableModel$UpdateDataTask

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

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

import java.beans.PropertyEditor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;

import org.pentaho.reporting.designer.core.editor.ReportRenderContext;
import org.pentaho.reporting.designer.core.util.FastPropertyEditorManager;
import org.pentaho.reporting.designer.core.util.exceptions.UncaughtExceptionsModel;
import org.pentaho.reporting.designer.core.util.table.ElementMetaDataTableModel;
import org.pentaho.reporting.designer.core.util.table.GroupingHeader;
import org.pentaho.reporting.designer.core.util.table.ResourcePropertyEditor;
import org.pentaho.reporting.designer.core.util.table.TableStyle;
import org.pentaho.reporting.engine.classic.core.Element;
import org.pentaho.reporting.engine.classic.core.ReportElement;
import org.pentaho.reporting.engine.classic.core.metadata.AttributeMetaData;
import org.pentaho.reporting.engine.classic.core.metadata.ElementType;
import org.pentaho.reporting.engine.classic.core.metadata.GroupedMetaDataComparator;
import org.pentaho.reporting.engine.classic.core.metadata.PlainMetaDataComparator;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.xmlns.common.AttributeMap;

/**
* Todo: Document me!
*
* @author Thomas Morgner
*/
public abstract class AbstractAttributeTableModel
    extends AbstractTableModel implements ElementMetaDataTableModel

{
  protected static final GroupingHeader[] EMPTY_GROUPINGS = new GroupingHeader[0];
  protected static final AttributeMetaData[] EMPTY_METADATA = new AttributeMetaData[0];

  protected class NotifyChangeTask implements Runnable
  {
    private DataBackend dataBackend;

    protected NotifyChangeTask(final DataBackend dataBackend)
    {
      this.dataBackend = dataBackend;
    }

    public void run()
    {
      setDataBackend(dataBackend);
      fireTableDataChanged();
    }
  }

  protected class SameElementsUpdateDataTask implements Runnable
  {
    private DataBackend dataBackend;

    protected SameElementsUpdateDataTask(final DataBackend elements)
    {
      this.dataBackend = elements;
    }

    public void run()
    {
      dataBackend.resetCache();
      try
      {
        if (SwingUtilities.isEventDispatchThread())
        {
          setDataBackend(dataBackend);
          fireTableDataChanged();
        }
        else
        {
          SwingUtilities.invokeAndWait(new NotifyChangeTask(dataBackend));
        }
      }
      catch (Exception e)
      {
        UncaughtExceptionsModel.getInstance().addException(e);
      }
    }
  }

  protected class UpdateDataTask implements Runnable
  {
    private ReportElement[] elements;

    protected UpdateDataTask(final ReportElement[] elements)
    {
      this.elements = elements.clone();
    }

    public void run()
    {
      try
      {
        final DataBackend dataBackend = updateData(elements);
        if (SwingUtilities.isEventDispatchThread())
        {
          setDataBackend(dataBackend);
          fireTableDataChanged();
        }
        else
        {
          SwingUtilities.invokeAndWait(new NotifyChangeTask(dataBackend));
        }
      }
      catch (Exception e)
      {
        UncaughtExceptionsModel.getInstance().addException(e);
      }
    }
  }

  protected static abstract class DataBackend
  {
    private AttributeMetaData[] metaData;
    private GroupingHeader[] groupings;

    public DataBackend()
    {
      groupings = EMPTY_GROUPINGS;
      metaData = EMPTY_METADATA;
    }

    public abstract void resetCache();

    public DataBackend(final AttributeMetaData[] metaData, final GroupingHeader[] groupings)
    {
      this.metaData = metaData;
      this.groupings = groupings;
    }

    public int getRowCount()
    {
      return metaData.length;
    }

    protected AttributeMetaData getMetaData(final int row)
    {
      //noinspection ReturnOfCollectionOrArrayField, as this is for internal use only
      return metaData[row];
    }

    protected GroupingHeader getGroupings(final int row)
    {
      //noinspection ReturnOfCollectionOrArrayField, as this is for internal use only
      return groupings[row];
    }

    protected GroupingHeader[] getGroupings()
    {
      return groupings;
    }
  }

  private DataBackend dataBackend, oldDataBackend;
  private TableStyle tableStyle;
  private ReportRenderContext reportRenderContext;

  protected AbstractAttributeTableModel()
  {
    tableStyle = TableStyle.GROUPED;
  }

  public int getRowCount()
  {
    return dataBackend.getRowCount();
  }

  protected AttributeMetaData getMetaData(final int row)
  {
    return dataBackend.getMetaData(row);
  }

  protected GroupingHeader getGroupings(final int row)
  {
    return dataBackend.getGroupings(row);
  }

  public TableStyle getTableStyle()
  {
    return tableStyle;
  }

  public void setTableStyle(final TableStyle tableStyle)
  {
    if (tableStyle == null)
    {
      throw new NullPointerException();
    }
    this.tableStyle = tableStyle;
    refreshData();
  }

  protected abstract void refreshData();

  protected static boolean isSameElements(final ReportElement[] elements,
                                          final ReportElement[] existingElements,
                                          final ElementType[] elementTypes)
  {
    if (elements == existingElements)
    {
      return true;
    }
    if (elements.length != existingElements.length)
    {
      // that is easy!
      return false;
    }

    for (int i = 0; i < elements.length; i++)
    {
      final Element element = (Element) elements[i];
      if (element.getObjectID() != null)
      {
        if (existingElements[i].getObjectID() != element.getObjectID())
        {
          return false;
        }
        if (elementTypes != null)
        {
          if (!element.getElementType().getClass().equals(elementTypes[i].getClass()))
          {
            return false;
          }
        }
      }
      else
      {
        if (existingElements[i] != element)
        {
          return false;
        }
      }
    }
    return true;
  }

  public synchronized DataBackend getDataBackend()
  {
    return dataBackend;
  }

  public synchronized void setDataBackend(final DataBackend dataBackend)
  {
    this.dataBackend = dataBackend;
  }

  /**
   * @param headers
   * @param metaData
   * @param elements
   * @return null - Concrete implementations MUST override this method and
   *         call super.createDataBackend(headers, metaData, elements) BEFORE any
   *         other code is executed.  Then they must return a implementation of
   *         Databackend
   */
  protected DataBackend createDataBackend(final GroupingHeader[] headers,
                                          final AttributeMetaData[] metaData,
                                          final ReportElement[] elements,
                                          final ElementType[] elementTypes)
  {
    oldDataBackend = this.getDataBackend();
    return null;
  }

  protected DataBackend updateData(final ReportElement[] elements)
  {
    final AttributeMetaData[] metaData = selectCommonAttributes(elements);
    final ArrayList<ElementType> elementTypesArray = new ArrayList<ElementType>();
    for (int i = 0; i < elements.length; i++)
    {
      final Element element = (Element) elements[i];
      elementTypesArray.add(element.getElementType());
    }
    final ElementType[] elementTypes = elementTypesArray.toArray(new ElementType[elementTypesArray.size()]);

    if (tableStyle == TableStyle.ASCENDING)
    {
      Arrays.sort(metaData, new PlainMetaDataComparator());
      return (createDataBackend(new GroupingHeader[metaData.length], metaData, elements, elementTypes));
    }
    else if (tableStyle == TableStyle.DESCENDING)
    {
      Arrays.sort(metaData, Collections.reverseOrder(new PlainMetaDataComparator()));
      return (createDataBackend(new GroupingHeader[metaData.length], metaData, elements, elementTypes));
    }
    else
    {
      GroupingHeader[] groupings;
      Arrays.sort(metaData, new GroupedMetaDataComparator());

      int groupCount = 0;
      final Locale locale = Locale.getDefault();
      if (metaData.length > 0)
      {
        String oldValue = null;
        for (int i = 0; i < metaData.length; i++)
        {
          final AttributeMetaData data = metaData[i];
          if (data.isHidden())
          {
            continue;
          }

          if (groupCount == 0)
          {
            groupCount = 1;
            final AttributeMetaData firstdata = metaData[i];
            oldValue = firstdata.getGrouping(locale);
            continue;
          }

          final String grouping = data.getGrouping(locale);
          if ((ObjectUtilities.equal(oldValue, grouping)) == false)
          {
            oldValue = grouping;
            groupCount += 1;
          }
        }
      }

      final AttributeMetaData[] groupedMetaData = new AttributeMetaData[metaData.length + groupCount];
      int targetIdx = 0;
      groupings = new GroupingHeader[groupedMetaData.length];
      GroupingHeader group = null;
      for (int sourceIdx = 0; sourceIdx < metaData.length; sourceIdx++)
      {
        final AttributeMetaData data = metaData[sourceIdx];
        if (data.isHidden())
        {
          continue;
        }

        if (sourceIdx == 0)
        {
          group = new GroupingHeader(data.getGrouping(locale));
          groupings[targetIdx] = group;
          targetIdx += 1;
        }
        else
        {
          final String newgroup = data.getGrouping(locale);
          //noinspection ConstantConditions
          if ((ObjectUtilities.equal(newgroup, group.getHeaderText())) == false)
          {
            group = new GroupingHeader(newgroup);
            groupings[targetIdx] = group;
            targetIdx += 1;
          }
        }

        groupings[targetIdx] = group;
        groupedMetaData[targetIdx] = data;
        targetIdx += 1;
      }

      if (oldDataBackend != null)
      {
        groupings = reconcileState(groupings, oldDataBackend.getGroupings());
      }

      return (createDataBackend(groupings, groupedMetaData, elements, elementTypes));
    }
  }

  /**
   * Uses the name of the old groupings to set the collapse status of the new
   * groupings so that when a user makes a selection not all of the groups
   * return to the expanded state.  In essence makes group collapses "sticky"
   * where the group heading hasn't changed.
   *
   * @param groupings
   * @param oldGroupings
   */
  private GroupingHeader[] reconcileState(final GroupingHeader[] groupings, final GroupingHeader[] oldGroupings)
  {
    for (final GroupingHeader header : groupings)
    {
      final GroupingHeader oldHeader = findFirstOccuranceOfHeaderTitle(oldGroupings, header.getHeaderText());
      if (oldHeader != null)
      {
        header.setCollapsed(oldHeader.isCollapsed());
      }
    }
    return groupings;
  }

  private GroupingHeader findFirstOccuranceOfHeaderTitle(final GroupingHeader[] headerArray, final String headerTitle)
  {
    for (final GroupingHeader header : headerArray)
    {
      if (header == null)
      {
        continue;
      }
      if (ObjectUtilities.equal(header.getHeaderText(), headerTitle))
      {
        return header;
      }
    }
    return null;
  }

  private static AttributeMetaData[] selectCommonAttributes(final ReportElement[] elements)
  {
    final AttributeMap attributes = new AttributeMap();
    final ArrayList<AttributeMetaData> selectedArrays = new ArrayList<AttributeMetaData>();
    for (int elementCount = 0; elementCount < elements.length; elementCount++)
    {
      final ReportElement element = elements[elementCount];
      final AttributeMetaData[] datas = element.getMetaData().getAttributeDescriptions();
      for (int j = 0; j < datas.length; j++)
      {
        final AttributeMetaData data = datas[j];

        final String name = data.getName();
        final String namespace = data.getNameSpace();

        if (data.isHidden())
        {
          attributes.setAttribute(namespace, name, Boolean.FALSE);
          continue;
        }

        final Object attribute = attributes.getAttribute(namespace, name);
        if (Boolean.TRUE.equals(attribute))
        {
          // fine, we already have a value for it.
        }
        else if (attribute == null)
        {
          // add it ..
          if (elementCount == 0)
          {
            attributes.setAttribute(namespace, name, Boolean.TRUE);
          }
          else
          {
            attributes.setAttribute(namespace, name, Boolean.FALSE);
          }
        }
      }
    }

    final String[] namespaces = attributes.getNameSpaces();
    for (int nsIdx = 0; nsIdx < namespaces.length; nsIdx++)
    {
      final String namespace = namespaces[nsIdx];
      final String[] names = attributes.getNames(namespace);
      for (int namesIdx = 0; namesIdx < names.length; namesIdx++)
      {
        final String name = names[namesIdx];
        final Object attribute = attributes.getAttribute(namespace, name);
        if (Boolean.TRUE.equals(attribute))
        {
          selectedArrays.add(find(elements[0].getMetaData().getAttributeDescriptions(), namespace, name));
        }
      }
    }

    return selectedArrays.toArray(new AttributeMetaData[selectedArrays.size()]);
  }

  private static AttributeMetaData find(final AttributeMetaData[] data, final String namespace, final String name)
  {
    for (int i = 0; i < data.length; i++)
    {
      final AttributeMetaData attributeMetaData = data[i];
      if (attributeMetaData.getName().equals(name) && attributeMetaData.getNameSpace().equals(namespace))
      {
        return attributeMetaData;
      }
    }
    return null;
  }

 
  protected PropertyEditor getDefaultEditor(final Class type, final String valueRole)
  {
    if (String.class.equals(type))
    {
      return null;
    }
    if (AttributeMetaData.VALUEROLE_RESOURCE.equals(valueRole))
    {
      return new ResourcePropertyEditor(reportRenderContext);
    }

    return FastPropertyEditorManager.findEditor(type);
  }

  public ReportRenderContext getReportRenderContext()
  {
    return reportRenderContext;
  }

  public void setReportRenderContext(final ReportRenderContext reportRenderContext)
  {
    this.reportRenderContext = reportRenderContext;
  }
}
TOP

Related Classes of org.pentaho.reporting.designer.core.editor.attributes.AbstractAttributeTableModel$UpdateDataTask

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.
div>