1 /*
   2  * Copyright (c) 1999, 2004, 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 
  45 /**
  46  * This is the symbol table entry for interfaces.
  47  **/
  48 public class InterfaceEntry extends SymtabEntry implements InterfaceType
  49 {
  50 
  51   protected InterfaceEntry ()
  52   {
  53     super ();
  54   } // ctor
  55 
  56   protected InterfaceEntry (InterfaceEntry that)
  57   {
  58     super (that);
  59     _derivedFromNames = (Vector)that._derivedFromNames.clone ();
  60     _derivedFrom      = (Vector)that._derivedFrom.clone ();
  61     _methods          = (Vector)that._methods.clone ();
  62     _allMethods       = (Vector)that._allMethods.clone ();
  63     forwardedDerivers = (Vector)that.forwardedDerivers.clone ();
  64     _contained        = (Vector)that._contained.clone ();
  65     _interfaceType    = that._interfaceType;
  66   } // ctor
  67 
  68   protected InterfaceEntry (SymtabEntry that, IDLID clone)
  69   {
  70     super (that, clone);
  71     if (module ().equals (""))
  72       module (name ());
  73     else if (!name ().equals (""))
  74       module (module () + "/" + name ());
  75   } // ctor
  76 
  77   public boolean isAbstract()
  78   {
  79       return _interfaceType == ABSTRACT ;
  80   }
  81 
  82   public boolean isLocal()
  83   {
  84       return _interfaceType == LOCAL ;
  85   }
  86 
  87   public boolean isLocalServant()
  88   {
  89       return _interfaceType == LOCALSERVANT ;
  90   }
  91 
  92   public boolean isLocalSignature()
  93   {
  94       return _interfaceType == LOCAL_SIGNATURE_ONLY ;
  95   }
  96 
  97   public Object clone ()
  98   {
  99     return new InterfaceEntry (this);
 100   } // clone
 101 
 102   /** Invoke the interface generator.
 103       @param symbolTable the symbol table is a hash table whose key is
 104        a fully qualified type name and whose value is a SymtabEntry or
 105        a subclass of SymtabEntry.
 106       @param stream the stream to which the generator should sent its output.
 107       @see SymtabEntry */
 108   public void generate (Hashtable symbolTable, PrintWriter stream)
 109   {
 110     interfaceGen.generate (symbolTable, this, stream);
 111   } // generate
 112 
 113   /** Access the interface generator.
 114       @return an object which implements the InterfaceGen interface.
 115       @see InterfaceGen */
 116   public Generator generator ()
 117   {
 118     return interfaceGen;
 119   } // generator
 120 
 121   /** Add an InterfaceEntry to the list of interfaces which this interface
 122       is derivedFrom.  During parsing, the parameter to this method COULD
 123       be a ForwardEntry, but when parsing is complete, calling derivedFrom
 124       will return a vector which only contains InterfaceEntry's. */
 125   public void addDerivedFrom (SymtabEntry derivedFrom)
 126   {
 127     _derivedFrom.addElement (derivedFrom);
 128   } // addDerivedFrom
 129 
 130   /** This method returns a vector of InterfaceEntry's. */
 131   public Vector derivedFrom ()
 132   {
 133     return _derivedFrom;
 134   } // derivedFrom
 135 
 136   /** Add to the list of derivedFrom names. */
 137   public void addDerivedFromName (String name)
 138   {
 139     _derivedFromNames.addElement (name);
 140   } // addDerivedFromName
 141 
 142   /** This method returns a vector of Strings, each of which is a fully
 143       qualified name of an interface. This vector corresponds to the
 144       derivedFrom vector.  The first element of this vector is the name
 145       of the first element of the derivedFrom vector, etc. */
 146   public Vector derivedFromNames ()
 147   {
 148     return _derivedFromNames;
 149   } // derivedFromNames
 150 
 151   /** Add a method/attribute to the list of methods. */
 152   public void addMethod (MethodEntry method)
 153   {
 154     _methods.addElement (method);
 155   } // addMethod
 156 
 157   /** This is a vector of MethodEntry's.  These are the methods and
 158       attributes contained within this Interface. */
 159   public Vector methods ()
 160   {
 161     return _methods;
 162   } // methods
 163 
 164   /** Add a symbol table entry to this interface's contained vector. */
 165   public void addContained (SymtabEntry entry)
 166   {
 167     _contained.addElement (entry);
 168   } // addContained
 169 
 170   /** This is a vector of SymtabEntry's.  Valid entries in this vector are:
 171       AttributeEntry, ConstEntry, EnumEntry, ExceptionEntry, MethodEntry,
 172       StructEntry, NativeEntry, TypedefEntry, UnionEntry.
 173       Note that the methods vector is a subset of this vector. */
 174   public Vector contained ()
 175   {
 176     return _contained;
 177   } // contained
 178 
 179   void methodsAddElement (MethodEntry method, Scanner scanner)
 180   {
 181     if (verifyMethod (method, scanner, false))
 182     {
 183       addMethod (method);
 184       _allMethods.addElement (method);
 185 
 186       // Add this method to the 'allMethods' list of any interfaces
 187       // which may have inherited this one when it was a forward
 188       // reference.
 189       addToForwardedAllMethods (method, scanner);
 190     }
 191   } // methodsAddElement
 192 
 193   void addToForwardedAllMethods (MethodEntry method, Scanner scanner)
 194   {
 195     Enumeration e = forwardedDerivers.elements ();
 196     while (e.hasMoreElements ())
 197     {
 198       InterfaceEntry derived = (InterfaceEntry)e.nextElement ();
 199       if (derived.verifyMethod (method, scanner, true))
 200         derived._allMethods.addElement (method);
 201     }
 202   } // addToForwardedAllMethods
 203 
 204   // Make sure a method by this name doesn't exist in this class or
 205   // in this class's parents
 206   private boolean verifyMethod (MethodEntry method, Scanner scanner, boolean clash)
 207   {
 208     boolean unique = true;
 209     String  lcName = method.name ().toLowerCase ();
 210     Enumeration e  = _allMethods.elements ();
 211     while (e.hasMoreElements ())
 212     {
 213       MethodEntry emethod = (MethodEntry)e.nextElement ();
 214 
 215       // Make sure the method doesn't exist either in its
 216       // original name or in all lower case.  In IDL, identifiers
 217       // which differ only in case are collisions.
 218       String lceName = emethod.name ().toLowerCase ();
 219       if (method != emethod && lcName.equals (lceName))
 220       {
 221         if (clash)
 222           ParseException.methodClash (scanner, fullName (), method.name ());
 223         else
 224           ParseException.alreadyDeclared (scanner, method.name ());
 225         unique = false;
 226         break;
 227       }
 228     }
 229     return unique;
 230   } // verifyMethod
 231 
 232   void derivedFromAddElement (SymtabEntry e, Scanner scanner)
 233   {
 234     addDerivedFrom (e);
 235     addDerivedFromName (e.fullName ());
 236     addParentType( e, scanner );
 237   } // derivedFromAddElement
 238 
 239   void addParentType (SymtabEntry e, Scanner scanner)
 240   {
 241     if (e instanceof ForwardEntry)
 242       addToDerivers ((ForwardEntry)e);
 243     else
 244     { // e instanceof InterfaceEntry
 245       InterfaceEntry derivedFrom = (InterfaceEntry)e;
 246 
 247       // Compare all of the parent's methods to the methods on this
 248       // interface, looking for name clashes:
 249       for ( Enumeration enumeration = derivedFrom._allMethods.elements ();
 250             enumeration.hasMoreElements (); )
 251       {
 252         MethodEntry method = (MethodEntry)enumeration.nextElement ();
 253         if ( verifyMethod (method, scanner, true))
 254           _allMethods.addElement (method);
 255 
 256         // Add this method to the 'allMethods' list of any interfaces
 257         // which may have inherited this one when it was a forward
 258         // reference:
 259         addToForwardedAllMethods (method, scanner);
 260       }
 261 
 262       // If any of the parent's parents are forward entries, make
 263       // sure this interface gets added to their derivers list so
 264       // that when the forward entry is defined, the 'allMethods'
 265       // list of this interface can be updated.
 266       lookForForwardEntrys (scanner, derivedFrom);
 267     }
 268   }  // addParentType
 269 
 270   private void lookForForwardEntrys (Scanner scanner, InterfaceEntry entry)
 271   {
 272     Enumeration parents = entry.derivedFrom ().elements ();
 273     while (parents.hasMoreElements ())
 274     {
 275       SymtabEntry parent = (SymtabEntry)parents.nextElement ();
 276       if (parent instanceof ForwardEntry)
 277         addToDerivers ((ForwardEntry)parent);
 278       else if (parent == entry)
 279         ParseException.selfInherit (scanner, entry.fullName ());
 280       else // it must be an InterfaceEntry
 281         lookForForwardEntrys (scanner, (InterfaceEntry)parent);
 282     }
 283   } // lookForForwardEntrys
 284 
 285   public boolean replaceForwardDecl (ForwardEntry oldEntry, InterfaceEntry newEntry)
 286   {
 287     int index = _derivedFrom.indexOf( oldEntry );
 288     if ( index >= 0 )
 289       _derivedFrom.setElementAt( newEntry, index );
 290     return (index >= 0);
 291   } // replaceForwardDecl
 292 
 293   private void addToDerivers (ForwardEntry forward)
 294   {
 295     // Add this interface to the derivers list on the forward entry
 296     // so that when the forward entry is defined, the 'allMethods'
 297     // list of this interface can be updated.
 298     forward.derivers.addElement (this);
 299     Enumeration e = forwardedDerivers.elements ();
 300     while (e.hasMoreElements ())
 301       forward.derivers.addElement ((InterfaceEntry)e.nextElement ());
 302   } // addToDerivers
 303 
 304   /** This method returns a vector of the elements in the state block.
 305       If it is null, this is not a stateful interface.  If it is non-null,
 306       but of zero length, then it is still stateful; it has no state
 307       entries itself, but it has an ancestor which does. */
 308   public Vector state ()
 309   {
 310     return _state;
 311   } // state
 312 
 313   public void initState ()
 314   {
 315     _state = new Vector ();
 316   } // initState
 317 
 318   public void addStateElement (InterfaceState state, Scanner scanner)
 319   {
 320     if (_state == null)
 321       _state = new Vector ();
 322     String name = state.entry.name ();
 323     for (Enumeration e = _state.elements (); e.hasMoreElements ();)
 324       if (name.equals (((InterfaceState) e.nextElement ()).entry.name ()))
 325         ParseException.duplicateState (scanner, name);
 326     _state.addElement (state);
 327   } // state
 328 
 329   public int getInterfaceType ()
 330   {
 331     return _interfaceType;
 332   }
 333 
 334   public void setInterfaceType (int type)
 335   {
 336     _interfaceType = type;
 337   }
 338 
 339   /** Get the allMethods vector. */
 340   public Vector allMethods ()
 341   {
 342     return _allMethods;
 343   }
 344 
 345   private Vector  _derivedFromNames = new Vector();
 346   private Vector  _derivedFrom      = new Vector();
 347   private Vector  _methods          = new Vector();
 348           Vector  _allMethods       = new Vector();
 349           Vector  forwardedDerivers = new Vector();
 350   private Vector  _contained        = new Vector();
 351   private Vector  _state            = null;
 352   private int _interfaceType         = NORMAL;
 353 
 354   static  InterfaceGen interfaceGen;
 355 } // class InterfaceEntry