/*
 * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
/*
 * COMPONENT_NAME: idl.parser
 *
 * ORIGINS: 27
 *
 * Licensed Materials - Property of IBM
 * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
 * RMI-IIOP v1.0
 *
 */

package com.sun.tools.corba.se.idl;

// NOTES:

import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import com.sun.tools.corba.se.idl.constExpr.Expression;
//<daz> import com.sun.tools.corba.se.idl.som.idlemit.TypeCode;

/**
* This is the symbol table entry for values.
**/
public class ValueEntry extends InterfaceEntry
{
  protected ValueEntry ()
  {
    super ();
  } // ctor

  protected ValueEntry (ValueEntry that)
  {
     super (that);
    _supportsNames = (Vector)that._supportsNames.clone ();
    _supports      = (Vector)that._supports.clone ();
    _initializers  = (Vector)that._initializers.clone ();
    _custom        = that._custom;
    _isSafe        = that._isSafe;
  } // ctor

  protected ValueEntry (SymtabEntry that, IDLID clone)
  {
    super (that, clone);
  } // ctor

  public Object clone ()
  {
    return new ValueEntry (this);
  } // clone

  /** Invoke the interface generator.
      @param symbolTable The symbol table is a hash table whose key is
       a fully qualified type name and whose value is a SymtabEntry or
       a subclass of SymtabEntry.
      @param stream The stream to which the generator should sent its output.
      @see SymtabEntry */
  public void generate (Hashtable symbolTable, PrintWriter stream)
  {
    valueGen.generate (symbolTable, this, stream);
  } // generate

  /** Access the value generator.
      @returns an object which implements the ValueGen interface.
      @see ValueGen */
  public Generator generator ()
  {
    return valueGen;
  } // generator

  /** Add an InterfaceEntry to the list of interfaces which this value
      supports.  During parsing, the parameter to this method COULD be a
      ForwardEntry, but when parsing is complete, calling supports will
      return a vector which only contains InterfaceEntry's. */
  public void addSupport (SymtabEntry supports)
  {
    _supports.addElement (supports);
  } // addSupport

  /** This method returns a vector of InterfaceEntry's. */
  public Vector supports ()
  {
    return _supports;
  } // supports

  /** Add to the list of support names. */
  public void addSupportName (String name)
  {
    _supportsNames.addElement (name);
  } // addSupportName

  /** This method returns a vector of Strings, each of which is a fully
      qualified name of an interface. This vector corresponds to the
      supports vector.  The first element of this vector is the name of
      the first element of the supports vector, etc. */
  public Vector supportsNames ()
  {
    return _supportsNames;
  } // supportsNames

  /** Add a parent value type to the list of parent types for the value.
      This method:
      <UL>
        <LI> Allows only the first added class to be concrete if the receiver is
             concrete.
        <LI> Does not allow any added classes to be concrete if the receiver is
             abstract.
        <LI> Does not allow duplicate classes to be added.
      </UL> */
  void derivedFromAddElement (SymtabEntry e, boolean isSafe, Scanner scanner)
  {
    if (((InterfaceType)e).getInterfaceType() != InterfaceType.ABSTRACT) {
      if (isAbstract ())
        ParseException.nonAbstractParent2 (scanner, fullName (), e.fullName ());
      else if (derivedFrom ().size () > 0)
        ParseException.nonAbstractParent3 (scanner, fullName (), e.fullName ());
    }

    if (derivedFrom ().contains (e))
      ParseException.alreadyDerived (scanner, e.fullName (), fullName ());

    if (isSafe)
      _isSafe = true;

    addDerivedFrom (e);
    addDerivedFromName (e.fullName ());
    addParentType (e, scanner);
  } // derivedFromAddElement

  void derivedFromAddElement (SymtabEntry e, Scanner scanner)
  {
    // This code must check for duplicate interfaces being supported...
    addSupport (e);
    addSupportName (e.fullName ());
    addParentType (e, scanner);
  } // derivedFromAddElement

  public boolean replaceForwardDecl (ForwardEntry oldEntry, InterfaceEntry newEntry)
  {
    if (super.replaceForwardDecl (oldEntry, newEntry))
      return true;
    int index = _supports.indexOf (oldEntry);
    if ( index >= 0)
      _supports.setElementAt (newEntry, index);
    return (index >= 0);
  }

  void initializersAddElement (MethodEntry method, Scanner scanner)
  {
    // Check to see if the parameter signature is a duplicate:
    Vector params = method.parameters ();
    int    args   = params.size ();
    for (Enumeration e = _initializers.elements (); e.hasMoreElements ();)
    {
      Vector params2 = ( (MethodEntry) e.nextElement ()).parameters ();
      if (args == params2.size ())
      {
        int i = 0;
        for (; i < args; i++)
          if (!((ParameterEntry)params.elementAt (i)).type ().equals (
                ((ParameterEntry)params2.elementAt (i)).type ()))
            break;
        if (i >= args)
          ParseException.duplicateInit (scanner);
      }
    }
    _initializers.addElement (method);
  } // initializersAddElement

  public Vector initializers ()
  {
    return _initializers;
  }

  /** Tag all methods introduced by the value type as 'value methods' so
      they can be differentiated in the emitters from any interface methods
      that the value type supports. */
  public void tagMethods ()
  {
    for (Enumeration e = methods ().elements (); e.hasMoreElements ();)
      ((MethodEntry)e.nextElement ()).valueMethod (true);
  }

  // <46082.03> Revert to "IDL:"-style (i.e., regular) repository ID.

  /** Calculate the 'repository ID' for the value. This method should not be
      called before the complete value type has been parsed, since it computes
      the repository ID by computing hashcodes using all information contained
      in the value type definition, not just the value type's fully qualified
      name.*/
  /*
  public void calcRepId ()
  {
    ValueRepositoryId repId = new ValueRepositoryId ();
    repId.addType (this);
    calcRepId (repId);
    String scopedName = fullName ();
    // KLR - following switched to new format 8/26/98 per Simon's request
    repositoryID (new RepositoryID ( "H:" + repId.getHashcode() + ":" + scopedName));
  } // calcRepId
  */

  /*
  public void calcRepId (ValueRepositoryId repId)
  {
    Vector baseClasses = derivedFrom ();
    if (baseClasses.size () >= 1)
      ((ValueEntry)baseClasses.elementAt (0)).calcRepId (repId);
    Vector state = state ();
    if (state != null)
      for (Enumeration e = state.elements (); e.hasMoreElements ();)
        calcTypedefType (((InterfaceState)e.nextElement ()).entry, repId);
  } // calcRepId

  private void calcValueType (ValueEntry entry, ValueRepositoryId repId)
  {
    if (repId.isNewType (entry))
    {
      //<daz> repId.addValue (TypeCode.tk_value);
      repId.addValue (org.omg.CORBA.TCKind._tk_value);
      entry.calcRepId (repId);
    }
  } // calcValueType

  private void calcValueBoxType (ValueBoxEntry entry, ValueRepositoryId repId)
  {
    if (repId.isNewType (entry))
    {
      //<daz> repId.addValue (TypeCode.tk_value_box);
      repId.addValue (org.omg.CORBA.TCKind._tk_value_box);
      entry.calcRepId (repId);
    }
  } // calcValueBoxType

  private void calcTypedefType (TypedefEntry entry, ValueRepositoryId repId)
  {
    if (repId.isNewType (entry))
    {
      Vector arrayInfo = entry.arrayInfo ();
      if (arrayInfo.size () > 0)
      {
        //<daz> repId.addValue (TypeCode.tk_array);
        repId.addValue (org.omg.CORBA.TCKind._tk_array);
        for (Enumeration e = arrayInfo.elements (); e.hasMoreElements ();)
          repId.addValue (((Number)((Expression)e.nextElement ()).value ()).intValue ());
      }
      calcType (entry.type (), repId);
    }
  } // calcTypedefType

  private void calcType (SymtabEntry entry, ValueRepositoryId repId)
  {
    if (entry instanceof TypedefEntry)
      calcTypedefType ((TypedefEntry)entry, repId);
    else if (entry instanceof PrimitiveEntry)
      calcPrimitiveType (entry, repId);
    else if (entry instanceof InterfaceEntry)
      //<daz> repId.addValue (TypeCode._tk_objref);
      repId.addValue (org.omg.CORBA.TCKind._tk_objref);
    else if (entry instanceof EnumEntry)
      //<daz> repId.addValue (TypeCode._tk_enum);
     repId.addValue (org.omg.CORBA.TCKind._tk_enum);
    else if (entry instanceof StringEntry)
     calcStringType ( (StringEntry) entry, repId);
    else if (entry instanceof SequenceEntry)
     calcSequenceType ( (SequenceEntry) entry, repId);
    else if (entry instanceof StructEntry)
      calcStructType ( (StructEntry) entry, repId);
    else if (entry instanceof UnionEntry)
      calcUnionType ( (UnionEntry) entry, repId);
    else if (entry instanceof ValueBoxEntry)
      calcValueBoxType ( (ValueBoxEntry) entry, repId);
    else if (entry instanceof ValueEntry)
      calcValueType ( (ValueEntry) entry, repId);
  } // calcType

  private static Hashtable primTypes;

  private void calcPrimitiveType (SymtabEntry entry, ValueRepositoryId repId)
  {
    if (primTypes == null)
    {
      primTypes = new Hashtable ();
      //<daz> primTypes.put ("short",          new Integer (TypeCode.tk_short  ));
      primTypes.put ("short",          new Integer (org.omg.CORBA.TCKind._tk_short  ));
      //<daz> primTypes.put ("long",           new Integer (TypeCode.tk_long   ));
      primTypes.put ("long",           new Integer (org.omg.CORBA.TCKind._tk_long   ));
      //<daz> primTypes.put ("unsigned short", new Integer (TypeCode.tk_ushort ));
      primTypes.put ("unsigned short", new Integer (org.omg.CORBA.TCKind._tk_ushort ));
      //<daz> primTypes.put ("unsigned long",  new Integer (TypeCode.tk_ulong  ));
      primTypes.put ("unsigned long",  new Integer (org.omg.CORBA.TCKind._tk_ulong  ));
      //<daz> primTypes.put ("char",           new Integer (TypeCode.tk_char   ));
      primTypes.put ("char",           new Integer (org.omg.CORBA.TCKind._tk_char   ));
      //<daz> primTypes.put ("wchar",          new Integer (TypeCode.tk_wchar  ));
      primTypes.put ("wchar",          new Integer (org.omg.CORBA.TCKind._tk_wchar  ));
      //<daz> primTypes.put ("float",          new Integer (TypeCode.tk_float  ));
      primTypes.put ("float",          new Integer (org.omg.CORBA.TCKind._tk_float  ));
      //<daz> primTypes.put ("double",         new Integer (TypeCode.tk_double ));
      primTypes.put ("double",         new Integer (org.omg.CORBA.TCKind._tk_double ));
      //<daz> primTypes.put ("boolean",        new Integer (TypeCode.tk_boolean));
      primTypes.put ("boolean",        new Integer (org.omg.CORBA.TCKind._tk_boolean));
      //<daz> primTypes.put ("octet",          new Integer (TypeCode.tk_octet  ));
      primTypes.put ("octet",          new Integer (org.omg.CORBA.TCKind._tk_octet  ));
      //<daz> primTypes.put ("any",            new Integer (TypeCode.tk_any    )); }
      primTypes.put ("any",            new Integer (org.omg.CORBA.TCKind._tk_any    ));
    }
    repId.addValue (((Integer)primTypes.get (entry.name ())).intValue ());
  } // calcPrimitiveType

  private void calcStringType (StringEntry entry, ValueRepositoryId repId)
  {
    repId.addValue (entry.name ().equals (Parser.overrideName ("string")) ?
        //<daz> TypeCode.tk_string:
        org.omg.CORBA.TCKind._tk_string :
        //<daz> TypeCode.tk_wstring);
        org.omg.CORBA.TCKind._tk_wstring);
    if (entry.maxSize () != null)
      try
      {
        repId.addValue ( ( (Number) (entry.maxSize ()).value ()). intValue ());
      }
      catch (Exception exception)
      {}
  } // calcStringType

  private void calcSequenceType (SequenceEntry entry, ValueRepositoryId repId)
  {
    //<daz> repId.addValue (TypeCode.tk_sequence);
    repId.addValue (org.omg.CORBA.TCKind._tk_sequence);
    if (entry.maxSize () != null)
      try
      {
        repId.addValue (((Number)(entry.maxSize ()).value ()).intValue ());
      }
      catch (Exception exception)
      {}
  } // calcSequenceType

  private void calcStructType (StructEntry entry, ValueRepositoryId repId)
  {
    if (repId.isNewType (entry))
    {
      //<daz> repId.addValue (TypeCode.tk_struct);
      repId.addValue (org.omg.CORBA.TCKind._tk_struct);
      for (Enumeration e = entry.members ().elements (); e.hasMoreElements ();)
        calcTypedefType ( (TypedefEntry) e.nextElement (), repId);
    }
  } // calcStructType

  private void calcUnionType (UnionEntry entry, ValueRepositoryId repId)
  {
    if (repId.isNewType (entry))
    {
      //<daz> repId.addValue (TypeCode.tk_union);
      repId.addValue (org.omg.CORBA.TCKind._tk_union);
      calcType (entry.type (), repId);
      for (Enumeration e = entry.branches ().elements (); e.hasMoreElements ();)
        calcTypedefType ( ( (UnionBranch) e.nextElement ()).typedef, repId);
    }
  } // calcUnionType
*/

  /** Get the 'custom' marshaling property. */
  public boolean isCustom ()
  {
    return _custom;
  }

  /** Set the 'custom' marshaling property. */
  public void setCustom (boolean isCustom)
  {
    _custom = isCustom;
  }

  /** Return whether or not the value type can be "safely" truncated to
      its concrete parent type. */
  public boolean isSafe ()
  {
    return _isSafe;
  }

  private Vector   _supportsNames = new Vector ();
  private Vector   _supports      = new Vector ();
  private Vector   _initializers  = new Vector ();
  private boolean  _custom        = false;
  private boolean  _isSafe        = false;

  static  ValueGen valueGen;
} // class ValueEntry
