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

Source Code of org.pentaho.reporting.designer.core.editor.expressions.ExpressionPropertiesTableModel

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

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

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.designer.core.editor.ReportDocumentContext;
import org.pentaho.reporting.designer.core.settings.WorkspaceSettings;
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.GroupedName;
import org.pentaho.reporting.designer.core.util.table.GroupingHeader;
import org.pentaho.reporting.designer.core.util.table.GroupingModel;
import org.pentaho.reporting.designer.core.util.table.TableStyle;
import org.pentaho.reporting.designer.core.util.undo.CompoundUndoEntry;
import org.pentaho.reporting.designer.core.util.undo.ExpressionPropertyChangeUndoEntry;
import org.pentaho.reporting.designer.core.util.undo.UndoEntry;
import org.pentaho.reporting.designer.core.util.undo.UndoManager;
import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition;
import org.pentaho.reporting.engine.classic.core.event.ReportModelEvent;
import org.pentaho.reporting.engine.classic.core.function.Expression;
import org.pentaho.reporting.engine.classic.core.metadata.ExpressionMetaData;
import org.pentaho.reporting.engine.classic.core.metadata.ExpressionPropertyMetaData;
import org.pentaho.reporting.engine.classic.core.metadata.ExpressionRegistry;
import org.pentaho.reporting.engine.classic.core.metadata.GroupedMetaDataComparator;
import org.pentaho.reporting.engine.classic.core.metadata.PlainMetaDataComparator;
import org.pentaho.reporting.engine.classic.core.util.beans.BeanException;
import org.pentaho.reporting.engine.classic.core.util.beans.BeanUtility;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;

public class ExpressionPropertiesTableModel
    extends AbstractTableModel implements ElementMetaDataTableModel, GroupingModel
{
  private static final Log logger = LogFactory.getLog(ExpressionPropertiesTableModel.class);

  private static final Expression[] EMPTY_ELEMENTS = new Expression[0];
  private static final ExpressionPropertyMetaData[] EMPTY_METADATA = new ExpressionPropertyMetaData[0];
  private static final GroupingHeader[] EMPTY_GROUPINGS = new GroupingHeader[0];
  private static final BeanUtility[] EMPTY_EDITORS = new BeanUtility[0];

  private ExpressionPropertyMetaData[] metaData;
  private GroupingHeader[] groupings;
  private TableStyle tableStyle;
  private Expression[] elements;
  private BeanUtility[] editors;
  private ReportDocumentContext activeContext;
  private boolean filterInlineExpressionProperty;

  public ExpressionPropertiesTableModel()
  {
    tableStyle = TableStyle.GROUPED;
    this.elements = EMPTY_ELEMENTS;
    this.metaData = EMPTY_METADATA;
    this.groupings = EMPTY_GROUPINGS;
    this.editors = EMPTY_EDITORS;
  }

  public boolean isFilterInlineExpressionProperty()
  {
    return filterInlineExpressionProperty;
  }

  public void setFilterInlineExpressionProperty(final boolean filterInlineExpressionProperty)
  {
    this.filterInlineExpressionProperty = filterInlineExpressionProperty;
  }

  public ReportDocumentContext getActiveContext()
  {
    return activeContext;
  }

  public void setActiveContext(final ReportDocumentContext activeContext)
  {
    this.activeContext = activeContext;
  }

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

  protected ExpressionPropertyMetaData getMetaData(final int row)
  {
    return metaData[row];
  }

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

  public TableStyle getTableStyle()
  {
    return tableStyle;
  }

  public void setTableStyle(final TableStyle tableStyle)
  {
    if (tableStyle == null)
    {
      throw new NullPointerException();
    }
    this.tableStyle = tableStyle;
    try
    {
      updateData(getData());
    }
    catch (IntrospectionException e)
    {
      UncaughtExceptionsModel.getInstance().addException(e);
      try
      {
        updateData(EMPTY_ELEMENTS);
      }
      catch (IntrospectionException e1)
      {
        // now this cannot happen ..
        UncaughtExceptionsModel.getInstance().addException(e);
      }
    }
  }

  protected void updateData(final Expression[] elements) throws IntrospectionException
  {
    this.elements = elements.clone();
    this.editors = new BeanUtility[elements.length];
    for (int i = 0; i < elements.length; i++)
    {
      this.editors[i] = new BeanUtility(elements[i]);
    }

    final ExpressionPropertyMetaData[] metaData = selectCommonAttributes();
    if (tableStyle == TableStyle.ASCENDING)
    {
      Arrays.sort(metaData, new PlainMetaDataComparator());
      this.groupings = new GroupingHeader[metaData.length];
      this.metaData = metaData;
    }
    else if (tableStyle == TableStyle.DESCENDING)
    {
      Arrays.sort(metaData, Collections.reverseOrder(new PlainMetaDataComparator()));
      this.groupings = new GroupingHeader[metaData.length];
      this.metaData = metaData;
    }
    else
    {
      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++)
        {
          if (groupCount == 0)
          {
            groupCount = 1;
            final ExpressionPropertyMetaData firstdata = metaData[i];
            oldValue = firstdata.getGrouping(locale);
            continue;
          }

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

      final ExpressionPropertyMetaData[] groupedMetaData = new ExpressionPropertyMetaData[metaData.length + groupCount];
      this.groupings = new GroupingHeader[groupedMetaData.length];
      int targetIdx = 0;
      GroupingHeader group = null;
      for (int sourceIdx = 0; sourceIdx < metaData.length; sourceIdx++)
      {
        final ExpressionPropertyMetaData data = metaData[sourceIdx];
        if (sourceIdx == 0)
        {
          group = new GroupingHeader(data.getGrouping(locale));
          groupings[targetIdx] = group;
          targetIdx += 1;
        }
        else
        {
          final String newgroup = data.getGrouping(locale);
          if ((ObjectUtilities.equal(newgroup, group.getHeaderText())) == false)
          {
            group = new GroupingHeader(newgroup);
            groupings[targetIdx] = group;
            targetIdx += 1;
          }
        }

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

      this.metaData = groupedMetaData;
    }

    fireTableDataChanged();
  }

  protected boolean isFiltered(final ExpressionPropertyMetaData metaData)
  {
    if (metaData.isHidden())
    {
      return true;
    }
    if (WorkspaceSettings.getInstance().isShowExpertItems() == false && metaData.isExpert())
    {
      return true;
    }
    if (WorkspaceSettings.getInstance().isShowDeprecatedItems() == false && metaData.isDeprecated())
    {
      return true;
    }
    if (isFilterInlineExpressionProperty() == false)
    {
      return false;
    }

    if ("name".equals(metaData.getName())) // NON-NLS
    {
      return true;
    }
    if ("dependencyLevel".equals(metaData.getName())) // NON-NLS
    {
      return true;
    }
    return false;
  }

  protected ExpressionPropertyMetaData[] selectCommonAttributes()
  {
    final HashMap<String, Boolean> attributes = new HashMap<String, Boolean>();
    final ArrayList<ExpressionPropertyMetaData> selectedArrays = new ArrayList<ExpressionPropertyMetaData>();
    for (int elementIdx = 0; elementIdx < elements.length; elementIdx++)
    {
      final Expression element = elements[elementIdx];
      final String key = element.getClass().getName();
      if (ExpressionRegistry.getInstance().isExpressionRegistered(key) == false)
      {
        // we cannot even attempt to edit such unknown expressions.
        return new ExpressionPropertyMetaData[0];
      }

      final ExpressionMetaData metaData =
          ExpressionRegistry.getInstance().getExpressionMetaData(key);

      final ExpressionPropertyMetaData[] datas = metaData.getPropertyDescriptions();
      for (int styleIdx = 0; styleIdx < datas.length; styleIdx++)
      {
        final ExpressionPropertyMetaData data = datas[styleIdx];
        if (isFiltered(data))
        {
          continue;
        }

        final String name = data.getName();
        final Object attribute = attributes.get(name);
        if (Boolean.TRUE.equals(attribute))
        {
          // fine, we already have a value for it.
        }
        else if (attribute == null)
        {
          // add it ..
          if (elementIdx == 0)
          {
            selectedArrays.add(data);
            attributes.put(name, Boolean.TRUE);
          }
          else
          {
            attributes.put(name, Boolean.FALSE);
          }
        }

      }
    }

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


  public void setData(final Expression[] elements)
  {
    try
    {
      updateData(elements);
    }
    catch (Exception e)
    {
      UncaughtExceptionsModel.getInstance().addException(e);
      try
      {
        updateData(EMPTY_ELEMENTS);
      }
      catch (IntrospectionException e1)
      {
        // this time it will not happen.
      }
    }
  }

  public Expression[] getData()
  {
    return elements.clone();
  }

  public int getColumnCount()
  {
    return 2;
  }

  public String getColumnName(final int column)
  {
    switch (column)
    {
      case 0:
        return EditorExpressionsMessages.getString("ExpressionPropertiesTableModel.NameColumn");
      case 1:
        return EditorExpressionsMessages.getString("ExpressionPropertiesTableModel.ValueColumn");
      default:
        throw new IllegalArgumentException();
    }
  }

  public Object getValueAt(final int rowIndex, final int columnIndex)
  {
    final ExpressionPropertyMetaData metaData = getMetaData(rowIndex);
    if (metaData == null)
    {
      return getGroupings(rowIndex);
    }

    switch (columnIndex)
    {
      case 0:
        return new GroupedName(metaData);
      case 1:
        return computeFullValue(metaData);
      default:
        throw new IndexOutOfBoundsException();
    }
  }

  public boolean isCellEditable(final int rowIndex, final int columnIndex)
  {
    final ExpressionPropertyMetaData metaData = getMetaData(rowIndex);
    if (metaData == null)
    {
      return false;
    }

    switch (columnIndex)
    {
      case 0:
        return false;
      case 1:
        return true;
      default:
        throw new IndexOutOfBoundsException();
    }
  }


  public void setValueAt(final Object aValue, final int rowIndex, final int columnIndex)
  {
    final ExpressionPropertyMetaData metaData = getMetaData(rowIndex);
    if (metaData == null)
    {
      return;
    }

    switch (columnIndex)
    {
      case 0:
        return;
      case 1:
      {
        if (defineFullValue(metaData, aValue))
        {
          if (activeContext != null)
          {
            final AbstractReportDefinition abstractReportDefinition = activeContext.getReportDefinition();
            for (int i = 0; i < elements.length; i++)
            {
              final Expression expression = elements[i];
              abstractReportDefinition.fireModelLayoutChanged
                  (abstractReportDefinition, ReportModelEvent.NODE_PROPERTIES_CHANGED, expression);
            }
          }
          fireTableDataChanged();
        }
        break;
      }
      default:
        throw new IndexOutOfBoundsException();
    }

  }

  private boolean defineFullValue(final ExpressionPropertyMetaData metaData,
                                  final Object value)
  {
    boolean changed = false;
    try
    {
      for (int i = 0; i < editors.length; i++)
      {
        final BeanUtility element = editors[i];
        final Object attribute = element.getProperty(metaData.getName());
        if ((ObjectUtilities.equal(attribute, value)) == false)
        {
          changed = true;
        }
      }

      if (changed)
      {
        final ReportDocumentContext activeContext1 = getActiveContext();
        final ArrayList<UndoEntry> undos = new ArrayList<UndoEntry>();

        for (int i = 0; i < elements.length; i++)
        {
          final BeanUtility element = editors[i];
          final String name = metaData.getName();
          if (activeContext1 != null)
          {
            final Object oldValue = element.getProperty(name);
            undos.add(new ExpressionPropertyChangeUndoEntry(elements[i], name, oldValue, value));
          }
          element.setProperty(name, value);
        }
        if (activeContext1 != null)
        {
          final UndoManager undo = activeContext1.getUndo();
          undo.addChange(EditorExpressionsMessages.getString("ExpressionPropertiesTableModel.UndoName"),
              new CompoundUndoEntry((UndoEntry[]) undos.toArray(new UndoEntry[undos.size()])));
        }
      }
    }
    catch (BeanException e)
    {
      UncaughtExceptionsModel.getInstance().addException(e);
    }

    return changed;
  }

  private Object computeFullValue(final ExpressionPropertyMetaData metaData)
  {
    try
    {
      Object lastElement = null;
      if (elements.length > 0)
      {
        final BeanUtility element = editors[0];
        lastElement = element.getProperty(metaData.getName());
      }
      return lastElement;
    }
    catch (BeanException e)
    {
      UncaughtExceptionsModel.getInstance().addException(e);
      return null;
    }
  }

  public Class getClassForCell(final int rowIndex, final int columnIndex)
  {
    final ExpressionPropertyMetaData metaData = getMetaData(rowIndex);
    if (metaData == null)
    {
      return GroupingHeader.class;
    }

    switch (columnIndex)
    {
      case 0:
        return GroupedName.class;
      case 1:
        return metaData.getPropertyType();
      default:
        throw new IndexOutOfBoundsException();
    }
  }

  public PropertyEditor getEditorForCell(final int aRowIndex, final int aColumnIndex)
  {
    final ExpressionPropertyMetaData metaData = getMetaData(aRowIndex);
    if (metaData == null)
    {
      // a header row
      return null;
    }

    try
    {
      switch (aColumnIndex)
      {
        case 0:
          return null;
        case 1:
          final PropertyEditor editor = metaData.getEditor();
          if (editor != null)
          {
            return editor;
          }

          final Class editorClass = metaData.getBeanDescriptor().getPropertyEditorClass();
          if (editorClass != null)
          {
            return (PropertyEditor) editorClass.newInstance();
          }

          if (String.class.equals(metaData.getPropertyType()))
          {
            return null;
          }

          return FastPropertyEditorManager.findEditor(metaData.getPropertyType());
        default:
          throw new IndexOutOfBoundsException();
      }
    }
    catch (Exception e)
    {
      if (logger.isTraceEnabled())
      {
        logger.trace("Failed to create property-editor", e); // NON-NLS
      }
      return null;
    }
  }

  public String getValueRole(final int row, final int column)
  {
    if (column != 1)
    {
      return null;
    }
    final ExpressionPropertyMetaData metaData = getMetaData(row);
    if (metaData == null)
    {
      return null;
    }
    return metaData.getPropertyRole();
  }

  public String[] getExtraFields(final int row, final int column)
  {
    if (column == 0)
    {
      return null;
    }
    final ExpressionPropertyMetaData metaData = getMetaData(row);
    if (metaData == null)
    {
      return null;
    }
    return metaData.getExtraCalculationFields();
  }

  public GroupingHeader getGroupHeader(final int index)
  {
    return getGroupings(index);
  }

  public boolean isHeaderRow(final int index)
  {
    return metaData[index] == null;
  }
}
TOP

Related Classes of org.pentaho.reporting.designer.core.editor.expressions.ExpressionPropertiesTableModel

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.