/* gnuDynArray.java --
   Copyright (C) 2005 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 gnu.CORBA.DynAn;

import gnu.CORBA.Unexpected;
import gnu.CORBA.HolderLocator;

import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.TypeCodePackage.BadKind;
import org.omg.CORBA.portable.Streamable;
import org.omg.DynamicAny.DynAny;
import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode;
import org.omg.DynamicAny.DynAnyPackage.InvalidValue;
import org.omg.DynamicAny.DynAnyPackage.TypeMismatch;
import org.omg.DynamicAny.DynArray;

import java.io.Serializable;

import java.lang.reflect.Array;
import java.lang.reflect.Field;

/**
 * Provides support for dynamic array or sequence, where all members have the
 * same final_type.
 *
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class gnuDynArray
  extends DivideableAny
  implements DynArray, Serializable
{
  /**
   * Use serialVersionUID for interoperability.
   */
  private static final long serialVersionUID = 1;

  /**
   * The component "official" type (may be alias).
   */
  final TypeCode official_components;

  /**
   * The component "final" type, after resolving any aliases.
   */
  final TypeCode final_components;

  /**
   * Creates new array.
   *
   * @param aType the final_type of array.
   * @param aFactory the factory, used to initialise default values.
   * @param orb the ORB to that this DynAny belongs.
   * @param initialise_array if false, the array is not initialised in
   * constructor.
   *
   *
   * @throws BAD_PARAM if the passed typecode does not provide the length().
   */
  public gnuDynArray(TypeCode oType, TypeCode aType, gnuDynAnyFactory aFactory,
                     ORB anOrb, boolean initialise_array
                    )
              throws BAD_PARAM
  {
    super(oType, aType, aFactory, anOrb);

    try
      {
        official_components = final_type.content_type();

        TypeCode component = official_components;
        while (component.kind().value() == TCKind._tk_alias)
          component = component.content_type();
        final_components = component;

        if (initialise_array)
          {
            array = new DynAny[ aType.length() ];
            for (int i = 0; i < array.length; i++)
              {
                array [ i ] =
                  factory.create_dyn_any_from_type_code(official_components);
              }
          }
      }
    catch (Exception e)
      {
        BAD_PARAM bad = new BAD_PARAM("Unable to initialise array");
        bad.initCause(e);
        throw bad;
      }
  }

  /**
   * Copy one DynAny into another.
   */
  public void assign(DynAny from)
              throws TypeMismatch
  {
    checkType(official_type, from.type());
    if (from instanceof DynArray && from.component_count() == array.length)
      {
        DynArray dyn = (DynArray) from;
        array = dyn.get_elements_as_dyn_any();
      }
    else
      throw new TypeMismatch();
  }

  /**
   * Create a copy.
   */
  public DynAny copy()
  {
    DynAny[] c = new DynAny[ array.length ];
    for (int i = 0; i < c.length; i++)
      {
        c [ i ] = array [ i ].copy();
      }

    gnuDynArray d =
      new gnuDynArray(official_type, final_type, factory, orb, false);
    d.array = c;
    return d;
  }

  /**
   * Get elements as array of anys.
   */
  public Any[] get_elements()
  {
    Any[] r = new Any[ array.length ];
    for (int i = 0; i < r.length; i++)
      r [ i ] = array [ i ].to_any();
    return r;
  }

  /** {@inheritDoc} */
  public DynAny[] get_elements_as_dyn_any()
  {
    DynAny[] a = new DynAny[ array.length ];
    for (int i = 0; i < a.length; i++)
      {
        a [ i ] = array [ i ].copy();
      }
    return a;
  }

  /**
   * Set elements when array of dyn anys is provided. This method can set nested
   * data structures as an array components.
   */
  public void set_elements_as_dyn_any(DynAny[] value)
                               throws InvalidValue, TypeMismatch
  {
    if (value.length != array.length)
      throw new InvalidValue(sizeMismatch(array.length, value.length));
    for (int i = 0; i < value.length; i++)
      {
        checkType(official_components, value [ i ].type());
        array [ i ].assign(value [ i ]);
      }
    pos = 0;
    valueChanged();
  }

  /**
   * Set elements when array of ordinary anys is provided.
   */
  public void set_elements(Any[] value)
                    throws InvalidValue, TypeMismatch
  {
    if (value.length != array.length)
      throw new InvalidValue(sizeMismatch(array.length, value.length));

    for (int i = 0; i < value.length; i++)
      {
        checkType(official_components, value [ i ].type());
        try
          {
            array [ i ] = factory.create_dyn_any(value [ i ]);
          }
        catch (InconsistentTypeCode e)
          {
            TypeMismatch t = new TypeMismatch();
            t.initCause(e);
            throw t;
          }
      }
    pos = 0;
    valueChanged();
  }

  /**
   * Done via reflection.
   */
  public Any to_any()
  {
    try
      {
        Streamable memberHolder =
          HolderLocator.createHolder(official_components);

        if (memberHolder == null)
          memberHolder = HolderLocator.createHolder(final_components);

        Class memberHolderClass = memberHolder.getClass();
        Class memberClass = memberHolderClass.getField("value").getType();

        Object members = Array.newInstance(memberClass, array.length);
        Object member;
        Any am;
        Field value = memberHolder.getClass().getField("value");

        for (int i = 0; i < array.length; i++)
          {
            // Recursive call should support multidimensional arrays.
            am = array [ i ].to_any();
            memberHolder = am.extract_Streamable();
            member = value.get(memberHolder);
            Array.set(members, i, member);
          }

        Streamable arrayHolder = HolderLocator.createHolder(official_type);
        arrayHolder.getClass().getField("value").set(arrayHolder, members);

        Any g = createAny();
        g.insert_Streamable(arrayHolder);
        g.type(official_type);
        return g;
      }
    catch (Exception e)
      {
        throw new Unexpected(e);
      }
  }

  /**
   * Done via reflection.
   */
  public void from_any(Any an_any)
                throws TypeMismatch, InvalidValue
  {
    checkType(official_type, an_any.type());
    try
      {
        Streamable s = an_any.extract_Streamable();
        Object members = s.getClass().getField("value").get(s);

        checkArrayValid(members);

        Any member;
        Streamable holder;
        Class holderClass = null;

        for (int i = 0; i < array.length; i++)
          {
            if (holderClass == null)
              {
                holder = HolderLocator.createHolder(official_components);
                if (holder == null)
                  holder = HolderLocator.createHolder(final_components);
                holderClass = holder.getClass();
              }
            else
              holder = (Streamable) holderClass.newInstance();

            member = createAny();
            holder.getClass().getField("value").set(holder,
                                                    Array.get(members, i)
                                                   );
            member.insert_Streamable(holder);
            member.type(official_components);

            // This may lead to recursion, supporting multidimensional
            // arrays.
            array [ i ].from_any(member);
          }
      }
    catch (Exception ex)
      {
        TypeMismatch t = new TypeMismatch();
        t.initCause(ex);
        throw t;
      }
    valueChanged();
  }

  /**
   * Check if array size is valid and (for sequences) resized
   * if required. Called from from_any.
   */
  protected void checkArrayValid(Object members)
                          throws TypeMismatch, InvalidValue
  {
    if (array.length != Array.getLength(members))
      throw new InvalidValue(sizeMismatch(array.length, Array.getLength(members)));
  }
}