package nl.tudelft.simulation.dsol.swing.introspection.gui;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.table.AbstractTableModel;
import org.djutils.immutablecollections.ImmutableCollection;
import org.djutils.logger.CategoryLogger;
import nl.tudelft.simulation.dsol.swing.introspection.table.DynamicTableModel;
import nl.tudelft.simulation.introspection.AbstractProperty;
import nl.tudelft.simulation.introspection.Introspector;
import nl.tudelft.simulation.introspection.Property;
import nl.tudelft.simulation.introspection.beans.BeanIntrospector;
/**
* A tablemodel used to manage and present the instances of a composite property.
*
* Copyright (c) 2002-2022 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
* for project information https://simulation.tudelft.nl. The DSOL
* project is distributed under a three-clause BSD-style license, which can be found at
*
* https://simulation.tudelft.nl/dsol/3.0/license.html.
*
* @author Peter Jacobs.
* @author Alexander Verbraeck.
* @author Niels Lang.
* @since 1.5
*/
public class CollectionTableModel extends AbstractTableModel implements IntrospectingTableModelInterface, DynamicTableModel
{
/** */
private static final long serialVersionUID = 20140831L;
/** the instances of the collection. */
protected Map instances = Collections.synchronizedMap(new LinkedHashMap(20));
/** the keys identifying specific instances. */
protected List keys = Collections.synchronizedList(new ArrayList(20));
/** the componentType. */
private Class> componentType = null;
/** the COLUMNS of this tabbleModel. */
private static final String[] COLUMNS = {"#", "+", "Instance"};
/** the expand button. */
private List buttons = Collections.synchronizedList(new ArrayList(20));
/** the parentProperty */
private Property parentProperty;
/** the introspector. */
private Introspector introspector;
/** The model manager. */
private ModelManager manager = new DefaultModelManager();
/** The highest key currently allocated. */
private int maxKey = 0;
/**
* constructs a new CollectionTableModel.
* @param parentProperty Property; the parentPropert
*/
public CollectionTableModel(final Property parentProperty)
{
this(parentProperty, new BeanIntrospector());
}
/**
* constructs a new CollectionTableModel.
* @param parentProperty Property; the parentProperty
* @param introspector Introspector; the introspector to use
*/
public CollectionTableModel(final Property parentProperty, final Introspector introspector)
{
Object values;
try
{
values = parentProperty.getValue();
}
catch (Exception e)
{
values = new String("-");
}
if (values.getClass().isArray())
{
for (int i = 0; i < Array.getLength(values); i++)
{
addValue(Array.get(values, i));
}
}
if (values instanceof Collection)
{
for (Iterator> i = ((Collection>) values).iterator(); i.hasNext();)
{
addValue(i.next());
}
}
if (values instanceof ImmutableCollection)
{
for (Iterator> i = ((ImmutableCollection>) values).iterator(); i.hasNext();)
{
addValue(i.next());
}
}
this.parentProperty = parentProperty;
this.introspector = introspector;
// Initialize buttons
for (int i = 0; i < this.instances.size(); i++)
{
this.buttons.add(new ExpandButton(getProperty(i), this));
}
}
/**
* Adds a new value to the managed composite property.
* @param value Object; the value to add
*/
private void addValue(final Object value)
{
Integer nextKey = Integer.valueOf(this.maxKey++);
this.keys.add(nextKey);
this.instances.put(nextKey, value);
}
/** {@inheritDoc} */
@Override
public int getRowCount()
{
return this.instances.size();
}
/** {@inheritDoc} */
@Override
public int getColumnCount()
{
return CollectionTableModel.COLUMNS.length;
}
/** {@inheritDoc} */
@Override
public Object getValueAt(final int rowIndex, final int columnIndex)
{
if (columnIndex == 0)
{
return Integer.valueOf(rowIndex);
}
if (columnIndex == 1)
{
return this.buttons.get(rowIndex);
}
if (columnIndex == 2)
{
return this.instances.get(this.keys.get(rowIndex));
}
return null;
}
/** {@inheritDoc} */
@Override
public String getColumnName(final int columnIndex)
{
return CollectionTableModel.COLUMNS[columnIndex];
}
/** {@inheritDoc} */
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex)
{
if (columnIndex == 1 || columnIndex == 2)
{
return true;
}
return false;
}
/** {@inheritDoc} */
@Override
public void setValueAt(final Object aValue, final int rowIndex, final int columnIndex)
{
if (columnIndex == 2)
{
Integer key = this.keys.get(rowIndex);
this.instances.put(key, aValue);
}
this.update();
}
/**
* updates the tableModel
*/
private void update()
{
// Generate a List reflecting changes
List