Package gov.nasa.arc.mct.table.model

Source Code of gov.nasa.arc.mct.table.model.ComponentTableModel

/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.arc.mct.table.model;

import gov.nasa.arc.mct.components.AbstractComponent;
import gov.nasa.arc.mct.components.FeedProvider;
import gov.nasa.arc.mct.components.Placeholder;
import gov.nasa.arc.mct.evaluator.api.Evaluator;
import gov.nasa.arc.mct.table.utils.NoSizeList;
import gov.nasa.arc.mct.table.view.DisplayedValue;
import gov.nasa.arc.mct.table.view.LabelAbbreviations;
import gov.nasa.arc.mct.table.view.TableCellSettings;
import gov.nasa.arc.mct.table.view.TableViewManifestation;

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Implements a labeled table model that represents a nested object
* structure of MCT components.
*/
public class ComponentTableModel extends LabeledTableModel {
 
  private static final long serialVersionUID = 1L;

  /** The 2-dimensional matrix of components making up this table model. */
  private TableStructure structure;
  private Map<String,List<Point>> componentLocations;
 
  private Map<String, Object> values = new HashMap<String, Object>();
  private Map<String, TableCellSettings> cellSettings = new HashMap<String, TableCellSettings>();
  private Map<String, LabelAbbreviations> cellLabelAbbreviations = new HashMap<String, LabelAbbreviations>();
 
  private NoSizeList<LabelAbbreviations> rowLabelAbbreviations = new NoSizeList<LabelAbbreviations>();
  private NoSizeList<LabelAbbreviations> columnLabelAbbreviations = new NoSizeList<LabelAbbreviations>();

  /** The maximum number of decimals for each column, if known. */
  private NoSizeList<Integer> maxDecimalsForColumn = new NoSizeList<Integer>();
 
  private TableViewManifestation tableViewManifestation;
 
  /**
   * Creates a new table model from a table structure object and a
   * labeling algorithm.
   *
   * @param structure the object representing the underlying MCT component structure.
   * @param algorithm the labeling algorithm.
   * @param tableViewManifestation the table view manifestation.
   */
  public ComponentTableModel(
      TableStructure structure,
      TableLabelingAlgorithm algorithm,
      TableViewManifestation tableViewManifestation
  ) {
    super(algorithm, TableOrientation.ROW_MAJOR);
    this.structure = structure;
    this.tableViewManifestation = tableViewManifestation;
    updateLocations();
  }
 
  /**
   * Updates the table structure in response to knowledge that the structure
   * of the root component in the table has changed. Users of the table model
   * should call this when they receive notification that children have been
   * added to or removed from the component that is backing up this model.
   */
  public void notifyTableStructureChanged() {
    structure.notifyTableStructureChanged();
  }
 
  /**
   * Returns a unique key for a given component. This key is used by the
   * code that responds to a feed update to pass along changes to the
   * component's value.
   *
   * @param component the component for which to determine the key
   * @return a unique key for the component
   */
  public String getKey(AbstractComponent component) {
    AbstractComponent delegate = component;
    Evaluator e = component.getCapability(Evaluator.class);
    if (e != null && component.getComponents().size() > 1) {
      return component.getComponentId();
    }
    FeedProvider fp = component.getCapability(FeedProvider.class);
    if (fp != null) {
      return fp.getSubscriptionId();
    }
   
    return delegate.getComponentId();
  }
 
  private void updateLocations() {
    componentLocations = new HashMap<String,List<Point>>();
    for (int row=0; row < structure.getRowCount(); ++row) {
      for (int col=0; col < structure.getColumnCount(); ++col) {
        AbstractComponent component = structure.getValue(row, col);
        if (component != null) {
          component.addViewManifestation(tableViewManifestation);
          List<Point> locations = componentLocations.get(getKey(component));
          if (locations == null) {
            locations = new ArrayList<Point>();
            componentLocations.put(getKey(component), locations);
          }
          locations.add(new Point(col,row));
        }
      }
    }
  }

  @Override
  protected int getObjectCount() {
    return structure.getRowCount();
  }
 
  @Override
  protected int getAttributeCount() {
    return structure.getColumnCount();
  }

  @Override
  protected String getObjectIdentifierAt(int rowIndex, int columnIndex) {
    AbstractComponent component = structure.getValue(rowIndex, columnIndex);
   
    if (component == null) {
      return "";
    } else if  (component == AbstractComponent.NULL_COMPONENT) {
      return "\u00A0";
    } else {
      return getCanonicalName(component);
    }
  }

  /**
   * Gets a complete identifier labeling the component. These <em>canonical
   * names</em> for each table cell are used in the table labeling algorithm
   * to calculate labels for columns, rows, and cells. The canonical name
   * is the canonical name of the feed provider, if it exists and is not
   * empty. Otherwise it is the display name for the component.
   *
   * @param component the component for which we need the canonical name
   * @return the canonical name for the component
   */
  private String getCanonicalName(AbstractComponent component) {
    String canonicalName = null;
   
    // Try to get the canonical name for the feed provider.
    FeedProvider feedProvider = component.getCapability(FeedProvider.class);
    if (feedProvider != null) {
      canonicalName = feedProvider.getCanonicalName();
    }
   
    // If the feed provider doesn't have a canonical name, use the component display name.
    if (canonicalName==null || canonicalName.isEmpty()) {
      canonicalName = component.getDisplayName();
    }
   
    return canonicalName;
  }
 
  @Override
  public Object getObjectAt(int rowIndex, int columnIndex) {
    AbstractComponent component = structure.getValue(rowIndex, columnIndex);
   
    if (component == null) {
      return null;
    } else if  (component == AbstractComponent.NULL_COMPONENT) {
      return "";
    } else {
      String cellName = getObjectName(rowIndex, columnIndex);

      Object value = getValueForComponent(component);
      if (value instanceof DisplayedValue) {
        DisplayedValue dv = (DisplayedValue) value;
        TableCellSettings cellSettings = getCellSettings(getKey(component));
        dv.setLabel(cellName!=null ? cellName : "");
        dv.setAlignment(cellSettings.getAlignment());
        dv.setNumberOfDecimals(cellSettings.getNumberOfDecimals());
      }
      return value;
    }
  }
 
  private Object getValueForComponent(AbstractComponent component) {
    Object value = values.get(getKey(component));
    if (value == null) {
      DisplayedValue displayedValue = new DisplayedValue();
      if (component.getCapability(Placeholder.class) != null) {
          displayedValue.setValue(component.getCapability(Placeholder.class).getPlaceholderValue());
      } else {
        displayedValue.setValue(component.getDisplayName());
      }
      return displayedValue;
    } else {
      return value;
    }
  }

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    return false;
  }

  /**
   * Sets the value of an object updated by a data feed. This change
   * is propogated to all table cells displaying that object.
   *
   * @param id the identifier for the object updated
   * @param value the new value to display
   */
  public void setValue(String id, Object value) {
    values.put(id, value);
    List<Point> locations = componentLocations.get(id);
    if (locations != null) {
      for (Point p : locations) {
        fireTableCellUpdated(p.y, p.x);
      }
    }
  }

  @Override
  public TableType getTableType() {
    return structure.getType();
  }

  @Override
  protected boolean canSetObjectAt(int rowIndex, int columnIndex, boolean isInsertRow, boolean isInsertColumn) {
    return structure.canSetValue(rowIndex, columnIndex, isInsertRow, isInsertColumn);
  }

  @Override
  protected void setObjectAt(Object value, int rowIndex, int columnIndex, boolean isInsertRow, boolean isInsertColumn) {
    structure.setValue(rowIndex, columnIndex, isInsertRow, isInsertColumn, (AbstractComponent) value);
    updateLocations();
  }

  @Override
  protected Object getStoredObjectAt(int objectIndex, int attributeIndex) {
    return structure.getValue(objectIndex, attributeIndex);
  }
 
  /**
   * Gets the component that will be modified to complete set a value at a particular
   * location. The new value may be inserted into a new row or column.
   *
   * @param rowIndex the row at which to place the new item
   * @param columnIndex the column at which to place the new item
   * @param isInsertRow true, if a new row should be inserted above the position
   * @param isInsertColumn true, if a new column should be inserted to the left of the position
   * @return the component that must be modified to set the value at the indicated position
   */
  public AbstractComponent getModifiedComponentAt(int rowIndex, int columnIndex, boolean isInsertRow, boolean isInsertColumn) {
    if (getOrientation() == TableOrientation.ROW_MAJOR) {
      return structure.getModifiedComponent(rowIndex, columnIndex, isInsertRow, isInsertColumn);
    } else {
      return structure.getModifiedComponent(columnIndex, rowIndex, isInsertColumn, isInsertRow);
    }
  }
 
  /**
   * Gets the cell settings for a particular component ID.
   *
   * @param id the identifier of the component in the cell
   * @return the cell settings, or a new set of default settings if no settings have been stored
   */
  public TableCellSettings getCellSettings(String id) {
    TableCellSettings settings = cellSettings.get(id);
    if (settings == null) {
      settings = new TableCellSettings();
      cellSettings.put(id, settings);
    }
    return settings;
  }
 
  /**
   * Notifies listeners that a table cell should be redrawn because its settings have changed.
   *
   * @param id the identifier for the component whose settings have changed
   */
  public void fireCellSettingsChanged(String id) {
    List<Point> locations = componentLocations.get(id);
    if (locations != null) {
      for (Point p : locations) {
        fireTableCellUpdated(p.y, p.x);
      }
    }
  }

  /**
   * Gets the row label abbreviations for a specified row.
   * 
   * @param row the row to retrieve abbreviations for
   * @return the abbreviations
   */
  public LabelAbbreviations getRowLabelAbbreviations(int row) {
    LabelAbbreviations abbrevs = rowLabelAbbreviations.get(row);
    if (abbrevs != null) {
      return abbrevs;
    } else {
      return new LabelAbbreviations();
    }
  }
 
  /**
   * Sets the row label abbreviations for a specified row.
   * 
   * @param rowIndex the row to set abbreviations for
   * @param abbreviations the new abbreviations
   */
  public void setRowLabelAbbreviations(int rowIndex, LabelAbbreviations abbreviations) {
    rowLabelAbbreviations.set(rowIndex, abbreviations);
    fireLabelsChanged();
  }
 
  /**
   * Gets column label abbreviations for a specified column.
   * 
   * @param column the column index to retrieve abbreviations for
   * @return the abbreviations
   */
  public LabelAbbreviations getColumnLabelAbbreviations(int column) {
    LabelAbbreviations abbrevs = columnLabelAbbreviations.get(column);
    if (abbrevs != null) {
      return abbrevs;
    } else {
      return new LabelAbbreviations();
    }
  }
 
  /**
   * Sets the column label abbreviations for a specified column.
   * 
   * @param columnIndex the column to set abbreviations for
   * @param abbreviations the new abbreviations
   */
  public void setColumnLabelAbbreviations(int columnIndex, LabelAbbreviations abbreviations) {
    columnLabelAbbreviations.set(columnIndex, abbreviations);
    fireLabelsChanged();
  }
 
  /**
   * Indicates that the labels of the rows or columns have changed.
   */
  public void fireHeaderLabelsChanged() {
    fireTableStructureChanged();
  }
 
  /**
   * Gets the cell label abbreviations for a specific feed provider ID.
   * 
   * @param id the feed provider ID (a PUI, if using ISP)
   * @return the cell label abbreviations
   */
  public LabelAbbreviations getCellLabelAbbreviations(String id) {
    LabelAbbreviations abbrevs = cellLabelAbbreviations.get(id);
    if (abbrevs == null) {
      abbrevs = new LabelAbbreviations();
      cellLabelAbbreviations.put(id, abbrevs);
    }
    return abbrevs;
  }
 
  /**
   * Sets the cell label abbreviations for a specific feed provider ID.
   * 
   * @param id the feed provider ID (a PUI, if using ISP)
   * @param abbreviations the new cell label abbreviations
   */
  public void setCellLabelAbbreviations(String id, LabelAbbreviations abbreviations) {
    cellLabelAbbreviations.put(id, abbreviations);
  }

  @Override
  public String getRowName(int rowIndex) {
    return abbreviateLabel(getFullRowName(rowIndex), getRowLabelAbbreviations(rowIndex));
  }
 
  private String abbreviateLabel(String fullLabel, LabelAbbreviations abbrevs) {
    if (abbrevs == null) {
      return fullLabel;
    } else {
      return abbrevs.applyAbbreviations(fullLabel);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    LabelAbbreviations x = getColumnLabelAbbreviations(columnIndex);
    return abbreviateLabel(getFullColumnName(columnIndex), getColumnLabelAbbreviations(columnIndex));
  }

  @Override
  public String getCellName(int rowIndex, int columnIndex) {
    String fullLabel = super.getCellName(rowIndex, columnIndex);
    AbstractComponent component = (AbstractComponent) getStoredValueAt(rowIndex, columnIndex);
    if (component == null) {
      return fullLabel;
    } else {
      LabelAbbreviations abbrevs = getCellLabelAbbreviations(getKey(component));
      return abbrevs.applyAbbreviations(fullLabel);
    }
  }
 
  @Override
  public void updateLabels() {
    super.updateLabels();

    // Forget about any abbreviations we're no longer using.
    rowLabelAbbreviations.truncate(getRowCount());
    columnLabelAbbreviations.truncate(getColumnCount());
  }

  @Override
  public boolean isSkeleton() {
    return structure.isSkeleton();
  }
 
  /**
   * Gets the maximum number of decimals shown in any cell in a column.
   * If we have already calculated the maximum for a column, returns it.
   * Otherwise iterates over all cells in the column to determine the
   * maximum, and remembers that value.
   *
   * @param columnIndex the column for which we want the max decimals setting
   * @return the maximum number of decimals shown in the column.
   */
  public int getMaxDecimalsForColumn(int columnIndex) {
    Integer decimals = maxDecimalsForColumn.get(columnIndex);
   
    if (decimals != null) {
      return decimals;
    }
   
    int maxDecimals = 0;
    for (int rowIndex=0; rowIndex < getRowCount(); ++rowIndex) {
      AbstractComponent component = (AbstractComponent) getStoredValueAt(rowIndex, columnIndex);
      if (component != null) {
        TableCellSettings cellSettings = getCellSettings(getKey(component));
        int cellDecimals = cellSettings.getNumberOfDecimals();
        if (cellDecimals < 0) {
          cellDecimals = TableCellSettings.DEFAULT_DECIMALS;
        }
       
        maxDecimals = Math.max(maxDecimals, cellDecimals);
      }
    }
   
    maxDecimalsForColumn.set(columnIndex, maxDecimals);
    return maxDecimals;
  }

  /**
   * Updates the maximumd decimals for a column. For simplicity,
   * just forgets all maximum decimal settings. The max for each
   * column will be updated when {@link #getMaxDecimalsForColumn(int)} is
   * called by the table cell renderer.
   */
  public void updateDecimalsForColumns() {
    maxDecimalsForColumn.clear();
  }
 
}
TOP

Related Classes of gov.nasa.arc.mct.table.model.ComponentTableModel

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.