/* TabularDataSupport.java -- Tables of composite data structures.
   Copyright (C) 2006, 2007 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package javax.management.openmbean;

import java.io.Serializable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Provides an implementation of the {@link TabularData}
 * interface using a {@link java.util.HashMap}.
 *
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @since 1.5
 */
public class TabularDataSupport
  implements TabularData, Serializable, Cloneable, Map<Object,Object>
{

  /**
   * Compatible with JDK 1.5
   */
  private static final long serialVersionUID = 5720150593236309827L;

  /**
   * Mapping of rows to column values.
   *
   * @serial the map of rows to column values.
   */
  private HashMap<Object,Object> dataMap;

  /**
   * The tabular type which represents this tabular data instance.
   *
   * @serial the type information for this instance.
   */
  private TabularType tabularType;

  /**
   * Constructs a new empty {@link TabularDataSupport} with the
   * specified type.  The type may not be null.  This constructor
   * simply calls the other, with the default initial capacity of
   * <code>101</code> and default load factor of <code>0.75</code>.
   *
   * @param type the tabular type of this tabular data instance.
   * @throws IllegalArgumentException if <code>type</code> is
   *                                  <code>null</code>.
   */
  public TabularDataSupport(TabularType type)
  {
    this(type, 101, 0.75f);
  }

  /**
   * Constructs a new empty {@link TabularDataSupport} with the
   * specified type and the supplied initial capacity and load factor
   * being used for the underlying {@link java.util.HashMap}.  The
   * type may not be null and the initial capacity and load factor
   * must be positive.
   *
   * @param type the tabular type of this tabular data instance.
   * @param cap the initial capacity of the underlying map.
   * @param lf the load factor of the underlying map.
   * @throws IllegalArgumentException if <code>type</code> is
   *                                  <code>null</code>, or
   *                                  <code>cap</code> or
   *                                  <code>lf</code> are
   *                                  negative.
   */
  public TabularDataSupport(TabularType type, int cap, float lf)
  {
    if (type == null)
      throw new IllegalArgumentException("The type may not be null.");
    tabularType = type;
    dataMap = new HashMap<Object,Object>(cap, lf);
  }

  /**
   * Calculates the index the specified {@link CompositeData} value
   * would have, if it was to be added to this {@link TabularData}
   * instance.  This method includes a check that the type of the
   * given value is the same as the row type of this instance, but not
   * a check for existing instances of the given value.  The value
   * must also not be <code>null</code>.  Possible indices are
   * selected by the {@link TabularType#getIndexNames()} method of
   * this instance's tabular type.  The returned indices are the
   * values of the fields in the supplied {@link CompositeData}
   * instance that match the names given in the {@link TabularType}.
   *
   * @param val the {@link CompositeData} value whose index should
   *            be calculated.
   * @return the index the value would take on, if it were to be added.
   * @throws NullPointerException if the value is <code>null</code>.
   * @throws InvalidOpenTypeException if the value does not match the
   *                                  row type of this instance.
   */
  public Object[] calculateIndex(CompositeData val)
  {
    if (!(val.getCompositeType().equals(tabularType.getRowType())))
      throw new InvalidOpenTypeException("The type of the given value " +
                                         "does not match the row type " +
                                         "of this instance.");
    List<String> indexNames = tabularType.getIndexNames();
    List<String> matchingIndicies = new ArrayList<String>(indexNames.size());
    for (String name : indexNames)
      matchingIndicies.add(val.get(name).toString());
    return matchingIndicies.toArray();
  }

  /**
   * Removes all {@link CompositeData} values from the table.
   */
  public void clear()
  {
    dataMap.clear();
  }

  /**
   * Returns a shallow clone of the information, as obtained by the
   * {@link Object} implementation of {@link Object#clone()}.  The map
   * is also cloned, but it still references the same objects.
   *
   * @return a shallow clone of this {@link TabularDataSupport}.
   */
  @SuppressWarnings("unchecked")
  public Object clone()
  {
    TabularDataSupport clone = null;
    try
      {
        clone = (TabularDataSupport) super.clone();
        clone.setMap((HashMap<Object,Object>) dataMap.clone());
      }
    catch (CloneNotSupportedException e)
      {
        /* This won't happen as we implement Cloneable */
      }
    return clone;
  }

  /**
   * Returns true iff this instance of the {@link TabularData} class
   * contains a {@link CompositeData} value at the specified index.
   * The method returns <code>false</code> if the given key can
   * not be cast to an {@link java.lang.Object} array; otherwise
   * it returns the result of {@link #containsKey(java.lang.Object[])}.
   *
   *
   * @param key the key to test for.
   * @return true if the key maps to a {@link CompositeData} value.
   */
  public boolean containsKey(Object key)
  {
    if (key instanceof Object[])
      return containsKey((Object[]) key);
    else
      return false;
  }

  /**
   * Returns true iff this instance of the {@link TabularData} class
   * contains a {@link CompositeData} value at the specified index.
   * In any other circumstance, including if the given key
   * is <code>null</code> or of the incorrect type, according to
   * the {@link TabularType} of this instance, this method returns
   * false.
   *
   * @param key the key to test for.
   * @return true if the key maps to a {@link CompositeData} value.
   */
  public boolean containsKey(Object[] key)
  {
    if (key == null)
      return false;
    if (!(isKeyValid(key)))
      return false;
    return dataMap.containsKey(key);
  }

  /**
   * Returns true iff this instance of the {@link TabularData} class
   * contains the specified {@link CompositeData} value.  If the given
   * value is not an instance of {@link CompositeData}, this method
   * simply returns false.
   *
   * @param val the value to test for.
   * @return true if the value exists.
   */
  public boolean containsValue(Object val)
  {
    if (val instanceof CompositeData)
      return containsValue((CompositeData) val);
    else
      return false;
  }

  /**
   * Returns true iff this instance of the {@link TabularData} class
   * contains the specified {@link CompositeData} value.
   * In any other circumstance, including if the given value
   * is <code>null</code> or of the incorrect type, according to
   * the {@link TabularType} of this instance, this method returns
   * false.
   *
   * @param val the value to test for.
   * @return true if the value exists.
   */
  public boolean containsValue(CompositeData val)
  {
    if (val == null)
      return false;
    if (!(val.getCompositeType().equals(tabularType.getRowType())))
      return false;
    return dataMap.containsValue(val);
  }

  /**
   * <p>
   * Returns a set view of the mappings in this Map.  Each element in the
   * set is a Map.Entry.  The set is backed by the map, so that changes in
   * one show up in the other.  Modifications made while an iterator is
   * in progress cause undefined behavior.  If the set supports removal,
   * these methods remove the underlying mapping from the map:
   * <code>Iterator.remove</code>, <code>Set.remove</code>,
   * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
   * Element addition, via <code>add</code> or <code>addAll</code>, is
   * not supported via this set.
   * </p>
   * <p>
   * <strong>Note</strong>: using the
   * {@link java.util.Map.Entry#setValue(Object) will cause corruption of
   * the index to row mappings.
   * </p>
   *
   * @return the set view of all mapping entries
   * @see java.util.Map.Entry
   */
  public Set<Map.Entry<Object,Object>> entrySet()
  {
    return dataMap.entrySet();
  }

  /**
   * Compares the specified object with this object for equality.
   * The object is judged equivalent if it is non-null, and also
   * an instance of {@link TabularData} with the same row type,
   * and {@link CompositeData} values.  The two compared instances may
   * be equivalent even if they represent different implementations
   * of {@link TabularData}.
   *
   * @param obj the object to compare for equality.
   * @return true if <code>obj</code> is equal to <code>this</code>.
   */
  public boolean equals(Object obj)
  {
    if (!(obj instanceof TabularData))
      return false;
    TabularData data = (TabularData) obj;
    return tabularType.equals(data.getTabularType()) &&
      dataMap.values().equals(data.values());
  }

  /**
   * Retrieves the value for the specified key by simply
   * calling <code>get((Object[]) key)</code>.
   *
   * @param key the key whose value should be returned.
   * @return the matching {@link CompositeData} value, or
   *         <code>null</code> if one does not exist.
   * @throws NullPointerException if the key is <code>null</code>.
   * @throws ClassCastException if the key is not an instance
   *                            of <code>Object[]</code>.
   * @throws InvalidKeyException if the key does not match
   *                             the {@link TabularType} of this
   *                             instance.
   */
  public Object get(Object key)
  {
    return get((Object[]) key);
  }

  /**
   * Retrieves the {@link CompositeData} value for the specified
   * key, or <code>null</code> if no such mapping exists.
   *
   * @param key the key whose value should be returned.
   * @return the matching {@link CompositeData} value, or
   *         <code>null</code> if one does not exist.
   * @throws NullPointerException if the key is <code>null</code>.
   * @throws InvalidKeyException if the key does not match
   *                             the {@link TabularType} of this
   *                             instance.
   */
  public CompositeData get(Object[] key)
  {
    if (!(isKeyValid(key)))
      throw new InvalidKeyException("The key does not match the " +
                                    "tabular type of this instance.");
    return (CompositeData) dataMap.get(key);
  }

  /**
   * Returns the tabular type which corresponds to this instance
   * of {@link TabularData}.
   *
   * @return the tabular type for this instance.
   */
  public TabularType getTabularType()
  {
    return tabularType;
  }

  /**
   * Returns the hash code of the composite data type.  This is
   * computed as the sum of the hash codes of each value, together
   * with the hash code of the tabular type.  These are the same
   * elements of the type that are compared as part of the {@link
   * #equals(java.lang.Object)} method, thus ensuring that the
   * hashcode is compatible with the equality test.
   *
   * @return the hash code of this instance.
   */
  public int hashCode()
  {
    return tabularType.hashCode() + dataMap.values().hashCode();
  }

  /**
   * Returns true if this {@link TabularData} instance
   * contains no {@link CompositeData} values.
   *
   * @return true if the instance is devoid of rows.
   */
  public boolean isEmpty()
  {
    return dataMap.isEmpty();
  }

  /**
   * Returns true if the given key is valid for the
   * @link{TabularType} of this instance.
   *
   * @return true if the key is valid.
   * @throws NullPointerException if <code>key</code>
   *                              is null.
   */
  private boolean isKeyValid(Object[] key)
  {
    Iterator<String> it = tabularType.getIndexNames().iterator();
    CompositeType rowType = tabularType.getRowType();
    for (int a = 0; it.hasNext(); ++a)
      {
        OpenType<?> type = rowType.getType(it.next());
        if (!(type.isValue(key[a])))
          return false;
      }
    return true;
  }

  /**
   * Returns a set view of the keys in this Map.  The set is backed by the
   * map, so that changes in one show up in the other.  Modifications made
   * while an iterator is in progress cause undefined behavior.  If the set
   * supports removal, these methods remove the underlying mapping from
   * the map: <code>Iterator.remove</code>, <code>Set.remove</code>,
   * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
   * Element addition, via <code>add</code> or <code>addAll</code>, is
   * not supported via this set.
   *
   * @return the set view of all keys
   */
  public Set<Object> keySet()
  {
    return dataMap.keySet();
  }

  /**
   * Adds the specified {@link CompositeData} value to the
   * table.  The value must be non-null, of the same type
   * as the row type of this instance, and must not have
   * the same index as an existing value.  The index is
   * calculated using the index names of the
   * {@link TabularType} for this instance.
   *
   * @param val the {@link CompositeData} value to add.
   * @throws NullPointerException if <code>val</code> is
   *                              <code>null</code>.
   * @throws InvalidOpenTypeException if the type of the
   *                                  given value does not
   *                                  match the row type.
   * @throws KeyAlreadyExistsException if the value has the
   *                                   same calculated index
   *                                   as an existing value.
   */
  public void put(CompositeData val)
  {
    Object[] key = calculateIndex(val);
    if (dataMap.containsKey(key))
      throw new KeyAlreadyExistsException("A value with this index " +
                                          "already exists.");
    dataMap.put(key, val);
  }

  /**
   * Adds the specified {@link CompositeData} value to the
   * table, ignoring the supplied key, by simply calling
   * <code>put((CompositeData) val)</code>.
   *
   * @param key ignored.
   * @param val the {@link CompositeData} value to add.
   * @return the {@link CompositeData} value.
   * @throws NullPointerException if <code>val</code> is
   *                              <code>null</code>.
   * @throws InvalidOpenTypeException if the type of the
   *                                  given value does not
   *                                  match the row type.
   * @throws KeyAlreadyExistsException if the value has the
   *                                   same calculated index
   *                                   as an existing value.
   */
  public Object put(Object key, Object val)
  {
    put((CompositeData) val);
    return val;
  }

  /**
   * Adds each of the specified {@link CompositeData} values
   * to the table.  Each element of the array must meet the
   * conditions given for the {@link #put(CompositeData)}
   * method.  In addition, the index of each value in the
   * array must be distinct from the index of the other
   * values in the array, as well as from the existing values
   * in the table.  The operation should be atomic; if one
   * value can not be added, then none of the values should
   * be.  If the array is <code>null</code> or empty, the
   * method simply returns.
   *
   * @param vals the {@link CompositeData} values to add.
   * @throws NullPointerException if a value from the array is
   *                              <code>null</code>.
   * @throws InvalidOpenTypeException if the type of a
   *                                  given value does not
   *                                  match the row type.
   * @throws KeyAlreadyExistsException if a value has the
   *                                   same calculated index
   *                                   as an existing value or
   *                                   of one of the other
   *                                   specified values.
   */
  public void putAll(CompositeData[] vals)
  {
    if (vals == null || vals.length == 0)
      return;
    Map<Object,Object> mapToAdd = new HashMap<Object,Object>(vals.length);
    for (int a = 0; a < vals.length; ++a)
      {
        Object[] key = calculateIndex(vals[a]);
        if (dataMap.containsKey(key))
          throw new KeyAlreadyExistsException("Element " + a + ": A " +
                                              "value with this index " +
                                              "already exists.");
        mapToAdd.put(key, vals[a]);
      }
    dataMap.putAll(mapToAdd);
  }

  /**
   * Converts each value from the specified map to a member of an
   * array of {@link CompositeData} values and adds them using {@link
   * #put(CompositeData[])}, if possible.  As in {@link
   * #put(Object,Object)}, the keys are simply ignored.  This method
   * is useful for adding the {@link CompositeData} values from a
   * different {@link TabularData} instance, which uses the same
   * {@link TabularType} but a different selection of index names, to
   * this one.  If the map is <code>null</code> or empty, the method
   * simply returns.
   *
   * @param m the map to add.  Only the values are used and must
   *          all be instances of {@link CompositeData}.
   * @throws NullPointerException if a value from the map is
   *                              <code>null</code>.
   * @throws ClassCastException if a value from the map is not
   *                            an instance of {@link CompositeData}.
   * @throws InvalidOpenTypeException if the type of the
   *                                  given value does not
   *                                  match the row type.
   * @throws KeyAlreadyExistsException if the value has the
   *                                   same calculated index
   *                                   as an existing value or
   *                                   of one of the other
   *                                   specified values.
   */
  public void putAll(Map<?,?> m)
  {
    if (m == null || m.size() == 0)
      return;
    Collection<?> vals = m.values();
    CompositeData[] data = new CompositeData[vals.size()];
    Iterator<?> it = vals.iterator();
    for (int a = 0; it.hasNext(); ++a)
      {
        data[a] = (CompositeData) it.next();
      }
    putAll(data);
  }

  /**
   * Removes the value for the specified key by simply
   * calling <code>remove((Object[]) key)</code>.
   *
   * @param key the key whose value should be removed.
   * @return the removed value, or <code>null</code> if
   *         there is no value for the given key.
   * @throws NullPointerException if the key is <code>null</code>.
   * @throws ClassCastException if the key is not an instance
   *                            of <code>Object[]</code>.
   * @throws InvalidOpenTypeException if the key does not match
   *                                  the {@link TabularType} of this
   *                                  instance.
   */
  public Object remove(Object key)
  {
    return remove((Object[]) key);
  }

  /**
   * Removes the {@link CompositeData} value located at the
   * specified index.  <code>null</code> is returned if the
   * value does not exist.  Otherwise, the removed value is
   * returned.
   *
   * @param key the key of the value to remove.
   * @return the removed value, or <code>null</code> if
   *         there is no value for the given key.
   * @throws NullPointerException if the key is <code>null</code>.
   * @throws InvalidOpenTypeException if the key does not match
   *                                  the {@link TabularType} of this
   *                                  instance.
   */
  public CompositeData remove(Object[] key)
  {
    if (!(isKeyValid(key)))
      throw new InvalidKeyException("The key does not match the " +
                                    "tabular type of this instance.");
    return (CompositeData) dataMap.remove(key);
  }

  /**
   * Private method to set the internal {@link java.util.Map}
   * instance (used in cloning).
   *
   * @param map the new map used.
   */
  private void setMap(HashMap<Object,Object> map)
  {
    dataMap = map;
  }

  /**
   * Returns the number of {@link CompositeData} values or rows
   * in the table.
   *
   * @return the number of rows in the table.
   */
  public int size()
  {
    return dataMap.size();
  }

  /**
   * Returns a textual representation of this instance.  This
   * is constructed using the class name
   * (<code>javax.management.openmbean.TabularDataSupport</code>)
   * and the result of calling <code>toString()</code> on the
   * tabular type and underlying hash map instance.
   *
   * @return a {@link java.lang.String} representation of the
   *         object.
   */
  public String toString()
  {
    return getClass().getName()
      + "[tabularType=" + tabularType
      + ",dataMap=" + dataMap
      + "]";
  }

  /**
   * Returns a collection (or bag) view of the values in this Map.  The
   * collection is backed by the map, so that changes in one show up in
   * the other.  Modifications made while an iterator is in progress cause
   * undefined behavior.  If the collection supports removal, these methods
   * remove the underlying mapping from the map: <code>Iterator.remove</code>,
   * <code>Collection.remove</code>, <code>removeAll</code>,
   * <code>retainAll</code>, and <code>clear</code>. Element addition, via
   * <code>add</code> or <code>addAll</code>, is not supported via this
   * collection.
   *
   * @return the collection view of all values
   */
  public Collection<Object> values()
  {
    return dataMap.values();
  }

}
