1 /*
   2  * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  * COMPONENT_NAME: idl.parser
  27  *
  28  * ORIGINS: 27
  29  *
  30  * Licensed Materials - Property of IBM
  31  * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
  32  * RMI-IIOP v1.0
  33  *
  34  */
  35 
  36 package com.sun.tools.corba.se.idl;
  37 
  38 // NOTES:
  39 
  40 import java.io.PrintWriter;
  41 import java.util.Enumeration;
  42 import java.util.Hashtable;
  43 import java.util.Vector;
  44 import com.sun.tools.corba.se.idl.constExpr.Expression;
  45 //<daz> import com.sun.tools.corba.se.idl.som.idlemit.TypeCode;
  46 
  47 /**
  48 * This is the symbol table entry for values.
  49 **/
  50 public class ValueEntry extends InterfaceEntry
  51 {
  52   protected ValueEntry ()
  53   {
  54     super ();
  55   } // ctor
  56 
  57   protected ValueEntry (ValueEntry that)
  58   {
  59      super (that);
  60     _supportsNames = (Vector)that._supportsNames.clone ();
  61     _supports      = (Vector)that._supports.clone ();
  62     _initializers  = (Vector)that._initializers.clone ();
  63     _custom        = that._custom;
  64     _isSafe        = that._isSafe;
  65   } // ctor
  66 
  67   protected ValueEntry (SymtabEntry that, IDLID clone)
  68   {
  69     super (that, clone);
  70   } // ctor
  71 
  72   public Object clone ()
  73   {
  74     return new ValueEntry (this);
  75   } // clone
  76 
  77   /** Invoke the interface generator.
  78       @param symbolTable The symbol table is a hash table whose key is
  79        a fully qualified type name and whose value is a SymtabEntry or
  80        a subclass of SymtabEntry.
  81       @param stream The stream to which the generator should sent its output.
  82       @see SymtabEntry */
  83   public void generate (Hashtable symbolTable, PrintWriter stream)
  84   {
  85     valueGen.generate (symbolTable, this, stream);
  86   } // generate
  87 
  88   /** Access the value generator.
  89       @return an object which implements the ValueGen interface.
  90       @see ValueGen */
  91   public Generator generator ()
  92   {
  93     return valueGen;
  94   } // generator
  95 
  96   /** Add an InterfaceEntry to the list of interfaces which this value
  97       supports.  During parsing, the parameter to this method COULD be a
  98       ForwardEntry, but when parsing is complete, calling supports will
  99       return a vector which only contains InterfaceEntry's. */
 100   public void addSupport (SymtabEntry supports)
 101   {
 102     _supports.addElement (supports);
 103   } // addSupport
 104 
 105   /** This method returns a vector of InterfaceEntry's. */
 106   public Vector supports ()
 107   {
 108     return _supports;
 109   } // supports
 110 
 111   /** Add to the list of support names. */
 112   public void addSupportName (String name)
 113   {
 114     _supportsNames.addElement (name);
 115   } // addSupportName
 116 
 117   /** This method returns a vector of Strings, each of which is a fully
 118       qualified name of an interface. This vector corresponds to the
 119       supports vector.  The first element of this vector is the name of
 120       the first element of the supports vector, etc. */
 121   public Vector supportsNames ()
 122   {
 123     return _supportsNames;
 124   } // supportsNames
 125 
 126   /** Add a parent value type to the list of parent types for the value.
 127       This method:
 128       <UL>
 129         <LI> Allows only the first added class to be concrete if the receiver is
 130              concrete.
 131         <LI> Does not allow any added classes to be concrete if the receiver is
 132              abstract.
 133         <LI> Does not allow duplicate classes to be added.
 134       </UL> */
 135   void derivedFromAddElement (SymtabEntry e, boolean isSafe, Scanner scanner)
 136   {
 137     if (((InterfaceType)e).getInterfaceType() != InterfaceType.ABSTRACT) {
 138       if (isAbstract ())
 139         ParseException.nonAbstractParent2 (scanner, fullName (), e.fullName ());
 140       else if (derivedFrom ().size () > 0)
 141         ParseException.nonAbstractParent3 (scanner, fullName (), e.fullName ());
 142     }
 143 
 144     if (derivedFrom ().contains (e))
 145       ParseException.alreadyDerived (scanner, e.fullName (), fullName ());
 146 
 147     if (isSafe)
 148       _isSafe = true;
 149 
 150     addDerivedFrom (e);
 151     addDerivedFromName (e.fullName ());
 152     addParentType (e, scanner);
 153   } // derivedFromAddElement
 154 
 155   void derivedFromAddElement (SymtabEntry e, Scanner scanner)
 156   {
 157     // This code must check for duplicate interfaces being supported...
 158     addSupport (e);
 159     addSupportName (e.fullName ());
 160     addParentType (e, scanner);
 161   } // derivedFromAddElement
 162 
 163   public boolean replaceForwardDecl (ForwardEntry oldEntry, InterfaceEntry newEntry)
 164   {
 165     if (super.replaceForwardDecl (oldEntry, newEntry))
 166       return true;
 167     int index = _supports.indexOf (oldEntry);
 168     if ( index >= 0)
 169       _supports.setElementAt (newEntry, index);
 170     return (index >= 0);
 171   }
 172 
 173   void initializersAddElement (MethodEntry method, Scanner scanner)
 174   {
 175     // Check to see if the parameter signature is a duplicate:
 176     Vector params = method.parameters ();
 177     int    args   = params.size ();
 178     for (Enumeration e = _initializers.elements (); e.hasMoreElements ();)
 179     {
 180       Vector params2 = ( (MethodEntry) e.nextElement ()).parameters ();
 181       if (args == params2.size ())
 182       {
 183         int i = 0;
 184         for (; i < args; i++)
 185           if (!((ParameterEntry)params.elementAt (i)).type ().equals (
 186                 ((ParameterEntry)params2.elementAt (i)).type ()))
 187             break;
 188         if (i >= args)
 189           ParseException.duplicateInit (scanner);
 190       }
 191     }
 192     _initializers.addElement (method);
 193   } // initializersAddElement
 194 
 195   public Vector initializers ()
 196   {
 197     return _initializers;
 198   }
 199 
 200   /** Tag all methods introduced by the value type as 'value methods' so
 201       they can be differentiated in the emitters from any interface methods
 202       that the value type supports. */
 203   public void tagMethods ()
 204   {
 205     for (Enumeration e = methods ().elements (); e.hasMoreElements ();)
 206       ((MethodEntry)e.nextElement ()).valueMethod (true);
 207   }
 208 
 209   // <46082.03> Revert to "IDL:"-style (i.e., regular) repository ID.
 210 
 211   /** Calculate the 'repository ID' for the value. This method should not be
 212       called before the complete value type has been parsed, since it computes
 213       the repository ID by computing hashcodes using all information contained
 214       in the value type definition, not just the value type's fully qualified
 215       name.*/
 216   /*
 217   public void calcRepId ()
 218   {
 219     ValueRepositoryId repId = new ValueRepositoryId ();
 220     repId.addType (this);
 221     calcRepId (repId);
 222     String scopedName = fullName ();
 223     // KLR - following switched to new format 8/26/98 per Simon's request
 224     repositoryID (new RepositoryID ( "H:" + repId.getHashcode() + ":" + scopedName));
 225   } // calcRepId
 226   */
 227 
 228   /*
 229   public void calcRepId (ValueRepositoryId repId)
 230   {
 231     Vector baseClasses = derivedFrom ();
 232     if (baseClasses.size () >= 1)
 233       ((ValueEntry)baseClasses.elementAt (0)).calcRepId (repId);
 234     Vector state = state ();
 235     if (state != null)
 236       for (Enumeration e = state.elements (); e.hasMoreElements ();)
 237         calcTypedefType (((InterfaceState)e.nextElement ()).entry, repId);
 238   } // calcRepId
 239 
 240   private void calcValueType (ValueEntry entry, ValueRepositoryId repId)
 241   {
 242     if (repId.isNewType (entry))
 243     {
 244       //<daz> repId.addValue (TypeCode.tk_value);
 245       repId.addValue (org.omg.CORBA.TCKind._tk_value);
 246       entry.calcRepId (repId);
 247     }
 248   } // calcValueType
 249 
 250   private void calcValueBoxType (ValueBoxEntry entry, ValueRepositoryId repId)
 251   {
 252     if (repId.isNewType (entry))
 253     {
 254       //<daz> repId.addValue (TypeCode.tk_value_box);
 255       repId.addValue (org.omg.CORBA.TCKind._tk_value_box);
 256       entry.calcRepId (repId);
 257     }
 258   } // calcValueBoxType
 259 
 260   private void calcTypedefType (TypedefEntry entry, ValueRepositoryId repId)
 261   {
 262     if (repId.isNewType (entry))
 263     {
 264       Vector arrayInfo = entry.arrayInfo ();
 265       if (arrayInfo.size () > 0)
 266       {
 267         //<daz> repId.addValue (TypeCode.tk_array);
 268         repId.addValue (org.omg.CORBA.TCKind._tk_array);
 269         for (Enumeration e = arrayInfo.elements (); e.hasMoreElements ();)
 270           repId.addValue (((Number)((Expression)e.nextElement ()).value ()).intValue ());
 271       }
 272       calcType (entry.type (), repId);
 273     }
 274   } // calcTypedefType
 275 
 276   private void calcType (SymtabEntry entry, ValueRepositoryId repId)
 277   {
 278     if (entry instanceof TypedefEntry)
 279       calcTypedefType ((TypedefEntry)entry, repId);
 280     else if (entry instanceof PrimitiveEntry)
 281       calcPrimitiveType (entry, repId);
 282     else if (entry instanceof InterfaceEntry)
 283       //<daz> repId.addValue (TypeCode._tk_objref);
 284       repId.addValue (org.omg.CORBA.TCKind._tk_objref);
 285     else if (entry instanceof EnumEntry)
 286       //<daz> repId.addValue (TypeCode._tk_enum);
 287      repId.addValue (org.omg.CORBA.TCKind._tk_enum);
 288     else if (entry instanceof StringEntry)
 289      calcStringType ( (StringEntry) entry, repId);
 290     else if (entry instanceof SequenceEntry)
 291      calcSequenceType ( (SequenceEntry) entry, repId);
 292     else if (entry instanceof StructEntry)
 293       calcStructType ( (StructEntry) entry, repId);
 294     else if (entry instanceof UnionEntry)
 295       calcUnionType ( (UnionEntry) entry, repId);
 296     else if (entry instanceof ValueBoxEntry)
 297       calcValueBoxType ( (ValueBoxEntry) entry, repId);
 298     else if (entry instanceof ValueEntry)
 299       calcValueType ( (ValueEntry) entry, repId);
 300   } // calcType
 301 
 302   private static Hashtable primTypes;
 303 
 304   private void calcPrimitiveType (SymtabEntry entry, ValueRepositoryId repId)
 305   {
 306     if (primTypes == null)
 307     {
 308       primTypes = new Hashtable ();
 309       //<daz> primTypes.put ("short",          new Integer (TypeCode.tk_short  ));
 310       primTypes.put ("short",          new Integer (org.omg.CORBA.TCKind._tk_short  ));
 311       //<daz> primTypes.put ("long",           new Integer (TypeCode.tk_long   ));
 312       primTypes.put ("long",           new Integer (org.omg.CORBA.TCKind._tk_long   ));
 313       //<daz> primTypes.put ("unsigned short", new Integer (TypeCode.tk_ushort ));
 314       primTypes.put ("unsigned short", new Integer (org.omg.CORBA.TCKind._tk_ushort ));
 315       //<daz> primTypes.put ("unsigned long",  new Integer (TypeCode.tk_ulong  ));
 316       primTypes.put ("unsigned long",  new Integer (org.omg.CORBA.TCKind._tk_ulong  ));
 317       //<daz> primTypes.put ("char",           new Integer (TypeCode.tk_char   ));
 318       primTypes.put ("char",           new Integer (org.omg.CORBA.TCKind._tk_char   ));
 319       //<daz> primTypes.put ("wchar",          new Integer (TypeCode.tk_wchar  ));
 320       primTypes.put ("wchar",          new Integer (org.omg.CORBA.TCKind._tk_wchar  ));
 321       //<daz> primTypes.put ("float",          new Integer (TypeCode.tk_float  ));
 322       primTypes.put ("float",          new Integer (org.omg.CORBA.TCKind._tk_float  ));
 323       //<daz> primTypes.put ("double",         new Integer (TypeCode.tk_double ));
 324       primTypes.put ("double",         new Integer (org.omg.CORBA.TCKind._tk_double ));
 325       //<daz> primTypes.put ("boolean",        new Integer (TypeCode.tk_boolean));
 326       primTypes.put ("boolean",        new Integer (org.omg.CORBA.TCKind._tk_boolean));
 327       //<daz> primTypes.put ("octet",          new Integer (TypeCode.tk_octet  ));
 328       primTypes.put ("octet",          new Integer (org.omg.CORBA.TCKind._tk_octet  ));
 329       //<daz> primTypes.put ("any",            new Integer (TypeCode.tk_any    )); }
 330       primTypes.put ("any",            new Integer (org.omg.CORBA.TCKind._tk_any    ));
 331     }
 332     repId.addValue (((Integer)primTypes.get (entry.name ())).intValue ());
 333   } // calcPrimitiveType
 334 
 335   private void calcStringType (StringEntry entry, ValueRepositoryId repId)
 336   {
 337     repId.addValue (entry.name ().equals (Parser.overrideName ("string")) ?
 338         //<daz> TypeCode.tk_string:
 339         org.omg.CORBA.TCKind._tk_string :
 340         //<daz> TypeCode.tk_wstring);
 341         org.omg.CORBA.TCKind._tk_wstring);
 342     if (entry.maxSize () != null)
 343       try
 344       {
 345         repId.addValue ( ( (Number) (entry.maxSize ()).value ()). intValue ());
 346       }
 347       catch (Exception exception)
 348       {}
 349   } // calcStringType
 350 
 351   private void calcSequenceType (SequenceEntry entry, ValueRepositoryId repId)
 352   {
 353     //<daz> repId.addValue (TypeCode.tk_sequence);
 354     repId.addValue (org.omg.CORBA.TCKind._tk_sequence);
 355     if (entry.maxSize () != null)
 356       try
 357       {
 358         repId.addValue (((Number)(entry.maxSize ()).value ()).intValue ());
 359       }
 360       catch (Exception exception)
 361       {}
 362   } // calcSequenceType
 363 
 364   private void calcStructType (StructEntry entry, ValueRepositoryId repId)
 365   {
 366     if (repId.isNewType (entry))
 367     {
 368       //<daz> repId.addValue (TypeCode.tk_struct);
 369       repId.addValue (org.omg.CORBA.TCKind._tk_struct);
 370       for (Enumeration e = entry.members ().elements (); e.hasMoreElements ();)
 371         calcTypedefType ( (TypedefEntry) e.nextElement (), repId);
 372     }
 373   } // calcStructType
 374 
 375   private void calcUnionType (UnionEntry entry, ValueRepositoryId repId)
 376   {
 377     if (repId.isNewType (entry))
 378     {
 379       //<daz> repId.addValue (TypeCode.tk_union);
 380       repId.addValue (org.omg.CORBA.TCKind._tk_union);
 381       calcType (entry.type (), repId);
 382       for (Enumeration e = entry.branches ().elements (); e.hasMoreElements ();)
 383         calcTypedefType ( ( (UnionBranch) e.nextElement ()).typedef, repId);
 384     }
 385   } // calcUnionType
 386 */
 387 
 388   /** Get the 'custom' marshaling property. */
 389   public boolean isCustom ()
 390   {
 391     return _custom;
 392   }
 393 
 394   /** Set the 'custom' marshaling property. */
 395   public void setCustom (boolean isCustom)
 396   {
 397     _custom = isCustom;
 398   }
 399 
 400   /** Return whether or not the value type can be "safely" truncated to
 401       its concrete parent type. */
 402   public boolean isSafe ()
 403   {
 404     return _isSafe;
 405   }
 406 
 407   private Vector   _supportsNames = new Vector ();
 408   private Vector   _supports      = new Vector ();
 409   private Vector   _initializers  = new Vector ();
 410   private boolean  _custom        = false;
 411   private boolean  _isSafe        = false;
 412 
 413   static  ValueGen valueGen;
 414 } // class ValueEntry