1 /*
   2  * Copyright (c) 1999, 2013, 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.toJava
  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.toJavaPortable;
  37 
  38 // NOTES:
  39 // -cast() does not support longlong types yet.
  40 // -Deal with typedef changes.
  41 // -Scoped names for the discriminator are ignored at the moment.
  42 // -F46082.51<daz> Remove -stateful feature; javaStatefulName() obsolete.
  43 // -D61056   <klr> Use Util.helperName
  44 
  45 import java.io.File;
  46 import java.io.IOException;
  47 import java.io.PrintWriter;
  48 import java.util.Enumeration;
  49 import java.util.Hashtable;
  50 import java.util.Vector;
  51 
  52 import com.sun.tools.corba.se.idl.GenFileStream;
  53 import com.sun.tools.corba.se.idl.ConstEntry;
  54 import com.sun.tools.corba.se.idl.EnumEntry;
  55 import com.sun.tools.corba.se.idl.InterfaceEntry;
  56 import com.sun.tools.corba.se.idl.PrimitiveEntry;
  57 import com.sun.tools.corba.se.idl.SequenceEntry;
  58 import com.sun.tools.corba.se.idl.StringEntry;
  59 import com.sun.tools.corba.se.idl.SymtabEntry;
  60 import com.sun.tools.corba.se.idl.TypedefEntry;
  61 import com.sun.tools.corba.se.idl.UnionBranch;
  62 import com.sun.tools.corba.se.idl.UnionEntry;
  63 
  64 import com.sun.tools.corba.se.idl.constExpr.Expression;
  65 import com.sun.tools.corba.se.idl.constExpr.EvaluationException;
  66 
  67 /**
  68  *
  69  **/
  70 public class UnionGen implements com.sun.tools.corba.se.idl.UnionGen, JavaGenerator
  71 {
  72   /**
  73    * Public zero-argument constructor.
  74    **/
  75   public UnionGen ()
  76   {
  77   } // ctor
  78 
  79   /**
  80    *
  81    **/
  82   public void generate (Hashtable symbolTable, UnionEntry u, PrintWriter s)
  83   {
  84     this.symbolTable = symbolTable;
  85     this.u           = u;
  86     init ();
  87 
  88     openStream ();
  89     if (stream == null)
  90       return;
  91     generateHelper ();
  92     generateHolder ();
  93     writeHeading ();
  94     writeBody ();
  95     writeClosing ();
  96     closeStream ();
  97     generateContainedTypes ();
  98   } // generate
  99 
 100   /**
 101    * Initialize members unique to this generator.
 102    **/
 103   protected void init ()
 104   {
 105     utype       = Util.typeOf (u.type ());
 106     unionIsEnum = utype instanceof EnumEntry;
 107   } // init
 108 
 109   /**
 110    *
 111    **/
 112   protected void openStream ()
 113   {
 114     stream = Util.stream (u, ".java");
 115   } // openStream
 116 
 117   /**
 118    *
 119    **/
 120   protected void generateHelper ()
 121   {
 122     ((Factories)Compile.compiler.factories ()).helper ().generate (symbolTable, u);
 123   } // generateHelper
 124 
 125   /**
 126    *
 127    **/
 128   protected void generateHolder ()
 129   {
 130    ((Factories)Compile.compiler.factories ()).holder ().generate (symbolTable, u);
 131   } // generateHolder
 132 
 133   /**
 134    *
 135    **/
 136   protected void writeHeading ()
 137   {
 138     // If the discriminator is an enum, assign the typePackage string.
 139     if (unionIsEnum)
 140       typePackage = Util.javaQualifiedName (utype) + '.';
 141     else
 142       typePackage = "";
 143 
 144     Util.writePackage (stream, u);
 145     Util.writeProlog (stream, ((GenFileStream)stream).name ());
 146 
 147     String className = u.name ();
 148     stream.println ("public final class " + u.name () + " implements org.omg.CORBA.portable.IDLEntity");
 149     stream.println ("{");
 150   } // writeHeading
 151 
 152   /**
 153    *
 154    **/
 155   protected void writeBody ()
 156   {
 157     // Write branches and populate quality arrays
 158     int size = u.branches ().size () + 1;
 159     Enumeration e = u.branches ().elements ();
 160     int i = 0;
 161     while (e.hasMoreElements ())
 162     {
 163       UnionBranch branch = (UnionBranch)e.nextElement ();
 164       Util.fillInfo (branch.typedef);
 165       // <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
 166       //stream.println ("  private " + Util.javaStatefulName (branch.typedef) + " ___" + branch.typedef.name () + ";");
 167       stream.println ("  private " + Util.javaName (branch.typedef) + " ___" + branch.typedef.name () + ";");
 168       ++i;
 169     }
 170     stream.println ("  private " + Util.javaName (utype) + " __discriminator;");
 171     stream.println ("  private boolean __uninitialized = true;");
 172 
 173     // Write ctor
 174     stream.println ();
 175     stream.println ("  public " + u.name () + " ()");
 176     stream.println ("  {");
 177     stream.println ("  }");
 178 
 179     // Write discriminator
 180     stream.println ();
 181     stream.println ("  public " + Util.javaName (utype) + " " + safeName (u, "discriminator") + " ()");
 182     stream.println ("  {");
 183     stream.println ("    if (__uninitialized)");
 184     stream.println ("      throw new org.omg.CORBA.BAD_OPERATION ();");
 185     stream.println ("    return __discriminator;");
 186     stream.println ("  }");
 187 
 188     // Write for each branch:
 189     // - setter
 190     // - getter
 191     // - private verifyXXX
 192     e = u.branches ().elements ();
 193     i = 0;
 194     while (e.hasMoreElements ())
 195     {
 196       UnionBranch branch = (UnionBranch)e.nextElement ();
 197       writeBranchMethods (stream, u, branch, i++);
 198     }
 199     if (u.defaultBranch () == null && !coversAll (u))
 200     {
 201       stream.println ();
 202       stream.println ("  public void _default ()");
 203       stream.println ("  {");
 204       stream.println ("    __discriminator = " + defaultDiscriminator (u) + ';');
 205       stream.println ("    __uninitialized = false;");
 206       stream.println ("  }");
 207 
 208       stream.println ();
 209       stream.println ("  public void _default (" + Util.javaName(utype) +
 210         " discriminator)");
 211       stream.println ("  {");
 212       stream.println ("    verifyDefault( discriminator ) ;" );
 213       stream.println ("    __discriminator = discriminator ;");
 214       stream.println ("    __uninitialized = false;");
 215       stream.println ("  }");
 216 
 217       writeVerifyDefault() ;
 218     }
 219     stream.println ();
 220   } // writeBody
 221 
 222   /**
 223    *
 224    **/
 225   protected void writeClosing ()
 226   {
 227     stream.println ("} // class " + u.name ());
 228   } // writeClosing
 229 
 230   /**
 231    *
 232    **/
 233   protected void closeStream ()
 234   {
 235     stream.close ();
 236   } // closeStream
 237 
 238   /**
 239    *
 240    **/
 241   protected void generateContainedTypes ()
 242   {
 243     Enumeration e = u.contained ().elements ();
 244     while (e.hasMoreElements ())
 245     {
 246       SymtabEntry entry = (SymtabEntry)e.nextElement ();
 247 
 248       // Don't generate contained entries if they are sequences.
 249       // Sequences are unnamed and since they translate to arrays,
 250       // no classes are generated for them, not even holders in this
 251       // case since they cannot be accessed outside of this union.
 252       if (!(entry instanceof SequenceEntry))
 253         entry.generate (symbolTable, stream);
 254     }
 255   } // generateContainedTypes
 256 
 257   private void writeVerifyDefault()
 258   {
 259     Vector labels = vectorizeLabels (u.branches (), true);
 260 
 261     if (Util.javaName(utype).equals ("boolean")) {
 262         stream.println( "" ) ;
 263         stream.println( "  private void verifyDefault (boolean discriminator)" ) ;
 264         stream.println( "  {" ) ;
 265         if (labels.contains ("true"))
 266             stream.println ("    if ( discriminator )");
 267         else
 268             stream.println ("    if ( !discriminator )");
 269         stream.println( "        throw new org.omg.CORBA.BAD_OPERATION();" ) ;
 270         stream.println( "  }" ) ;
 271         return;
 272     }
 273 
 274     stream.println( "" ) ;
 275     stream.println( "  private void verifyDefault( " + Util.javaName(utype) +
 276         " value )" ) ;
 277     stream.println( "  {" ) ;
 278 
 279     if (unionIsEnum)
 280         stream.println( "    switch (value.value()) {" ) ;
 281     else
 282         stream.println( "    switch (value) {" ) ;
 283 
 284     Enumeration e = labels.elements() ;
 285     while (e.hasMoreElements()) {
 286         String str = (String)(e.nextElement()) ;
 287         stream.println( "      case " + str + ":" ) ;
 288     }
 289 
 290     stream.println( "        throw new org.omg.CORBA.BAD_OPERATION() ;" ) ;
 291     stream.println( "" ) ;
 292     stream.println( "      default:" ) ;
 293     stream.println( "        return;" ) ;
 294     stream.println( "    }" ) ;
 295     stream.println( "  }" ) ;
 296   }
 297 
 298   private String defaultDiscriminator (UnionEntry u)
 299   {
 300     Vector labels = vectorizeLabels (u.branches (), false );
 301     String ret = null;
 302     SymtabEntry utype = Util.typeOf (u.type ());
 303     if (utype instanceof PrimitiveEntry  && utype.name ().equals ("boolean")) {
 304         // If it got this far, then:
 305         // - there is only one branch;
 306         // - that branch has only one label.
 307         if (labels.contains ("true"))
 308             ret = "false";
 309         else
 310             ret = "true";
 311     } else if (utype.name ().equals ("char")) {
 312         // This doesn't handle '\u0030' == '0'.  Unions are so
 313         // seldom used.  I don't have time to make this perfect.
 314         int def = 0;
 315         String string = "'\\u0000'";
 316         while (def != 0xFFFF && labels.contains (string))
 317             if (++def / 0x10 == 0)
 318                 string = "'\\u000" + def + "'";
 319             else if (def / 0x100 == 0)
 320                 string = "\\u00" + def + "'";
 321             else if (def / 0x1000 == 0)
 322                 string = "\\u0" + def + "'";
 323             else
 324                 string = "\\u" + def + "'";
 325         ret = string;
 326     } else if (utype instanceof EnumEntry) {
 327         Enumeration e = labels.elements ();
 328         EnumEntry enumEntry = (EnumEntry)utype;
 329         Vector enumList = (Vector)enumEntry.elements ().clone ();
 330         // cull out those elements in the enumeration list that are
 331         // in the cases of this union
 332         while (e.hasMoreElements ())
 333             enumList.removeElement (e.nextElement ());
 334         // If all of the enum elements are covered in this union and
 335         // there is a default statement, just pick one of the
 336         // elements for the default.  If there are enum elements
 337         // which are NOT covered by the cases, pick one as the
 338         // default.
 339         if (enumList.size () == 0)
 340             ret = typePackage + (String)enumEntry.elements ().lastElement ();
 341         else
 342             ret = typePackage + (String)enumList.firstElement ();
 343     } else if (utype.name ().equals ("octet")) {
 344         short def = Byte.MIN_VALUE;
 345         while (def != Byte.MAX_VALUE && labels.contains (Integer.toString (def)))
 346             ++def;
 347         ret = Integer.toString (def);
 348     } else if (utype.name ().equals ("short")) {
 349         short def = Short.MIN_VALUE;
 350         while (def != Short.MAX_VALUE && labels.contains (Integer.toString (def)))
 351             ++def;
 352         ret = Integer.toString (def);
 353     } else if (utype.name ().equals ("long")) {
 354         int def = Integer.MIN_VALUE;
 355         while (def != Integer.MAX_VALUE && labels.contains (Integer.toString (def)))
 356             ++def;
 357         ret = Integer.toString (def);
 358     } else if (utype.name ().equals ("long long")) {
 359         long def = Long.MIN_VALUE;
 360         while (def != Long.MAX_VALUE && labels.contains (Long.toString (def)))
 361             ++def;
 362         ret = Long.toString (def);
 363     } else if (utype.name ().equals ("unsigned short")) {
 364         short def = 0;
 365         while (def != Short.MAX_VALUE && labels.contains (Integer.toString (def)))
 366             ++def;
 367         ret = Integer.toString (def);
 368     } else if (utype.name ().equals ("unsigned long")) {
 369         int def = 0;
 370         while (def != Integer.MAX_VALUE && labels.contains (Integer.toString (def)))
 371             ++def;
 372         ret = Integer.toString (def);
 373     } else if (utype.name ().equals ("unsigned long long")) {
 374         long def = 0;
 375         while (def != Long.MAX_VALUE && labels.contains (Long.toString (def)))
 376             ++def;
 377         ret = Long.toString (def);
 378     }
 379 
 380     return ret;
 381   } // defaultDiscriminator
 382 
 383   /**
 384    *
 385    **/
 386   private Vector vectorizeLabels (Vector branchVector, boolean useIntsForEnums )
 387   {
 388     Vector mergedLabels = new Vector ();
 389     Enumeration branches = branchVector.elements ();
 390     while (branches.hasMoreElements ())
 391     {
 392       UnionBranch branch = (UnionBranch)branches.nextElement ();
 393       Enumeration labels = branch.labels.elements ();
 394       while (labels.hasMoreElements ())
 395       {
 396         Expression expr = (Expression)labels.nextElement ();
 397         String str ;
 398 
 399         if (unionIsEnum)
 400           if (useIntsForEnums)
 401             str = typePackage + "_" + Util.parseExpression( expr ) ;
 402           else
 403             str = typePackage + Util.parseExpression( expr ) ;
 404         else
 405           str = Util.parseExpression( expr ) ;
 406 
 407         mergedLabels.addElement (str);
 408       }
 409     }
 410     return mergedLabels;
 411   } // vectorizeLabels
 412 
 413   /**
 414    *
 415    **/
 416   private String safeName (UnionEntry u, String name)
 417   {
 418     Enumeration e = u.branches ().elements ();
 419     while (e.hasMoreElements ())
 420       if (((UnionBranch)e.nextElement ()).typedef.name ().equals (name))
 421       {
 422         name = '_' + name;
 423         break;
 424       }
 425     return name;
 426   } // safeName
 427 
 428   /**
 429    *
 430    **/
 431   private boolean coversAll (UnionEntry u)
 432   {
 433     // This assumes that it is not possible to cover types other than
 434     // boolean and enums.  This is not quite correct, but since octet
 435     // is not a valid discriminator type, it's not too bad in practice.
 436     // It may also be possible to cover a char type, but we won't worry
 437     // about that either.
 438     SymtabEntry utype = Util.typeOf (u.type ());
 439 
 440     boolean coversAll = false;
 441     if (utype.name ().equals ("boolean")) {
 442       if (u.branches ().size () == 2)
 443         coversAll = true;
 444     } else if (utype instanceof EnumEntry) {
 445       Vector labels = vectorizeLabels (u.branches (), true);
 446       if (labels.size () == ((EnumEntry)utype).elements ().size ())
 447         coversAll = true;
 448     }
 449 
 450     return coversAll;
 451   } // coversAll
 452 
 453   /**
 454    *
 455    **/
 456   private void writeBranchMethods (PrintWriter stream, UnionEntry u, UnionBranch branch, int i)
 457   {
 458     // Write getter
 459     stream.println ();
 460     // <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
 461     //stream.println ("  public " + Util.javaStatefulName (branch.typedef) + " " + branch.typedef.name () + " ()");
 462     stream.println ("  public " + Util.javaName (branch.typedef) + " " + branch.typedef.name () + " ()");
 463     stream.println ("  {");
 464     stream.println ("    if (__uninitialized)");
 465     stream.println ("      throw new org.omg.CORBA.BAD_OPERATION ();");
 466     stream.println ("    verify" + branch.typedef.name () + " (__discriminator);");
 467     stream.println ("    return ___" + branch.typedef.name () + ";");
 468     stream.println ("  }");
 469 
 470     // Write setter(s)
 471     stream.println ();
 472     // <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
 473     //stream.println ("  public void " + branch.typedef.name () + " (" + Util.javaStatefulName (branch.typedef) + " value)");
 474     stream.println ("  public void " + branch.typedef.name () + " (" + Util.javaName (branch.typedef) + " value)");
 475     stream.println ("  {");
 476     if (branch.labels.size () == 0)
 477     {
 478       // This is a default branch
 479       stream.println ("    __discriminator = " + defaultDiscriminator (u) + ";");
 480     }
 481     else
 482     {
 483       // This is a non-default branch
 484       if (unionIsEnum)
 485         stream.println ("    __discriminator = " + typePackage + Util.parseExpression ((Expression)branch.labels.firstElement ()) + ";");
 486       else
 487         stream.println ("    __discriminator = " + cast ((Expression)branch.labels.firstElement (), u.type ()) + ";");
 488     }
 489     stream.println ("    ___" + branch.typedef.name () + " = value;");
 490     stream.println ("    __uninitialized = false;");
 491     stream.println ("  }");
 492 
 493     SymtabEntry utype = Util.typeOf (u.type ());
 494 
 495     // If there are multiple labels for one branch, write the
 496     // setter that takes a discriminator.
 497     if (branch.labels.size () > 0 || branch.isDefault)
 498     {
 499       stream.println ();
 500       // <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
 501       //stream.println ("  public void " + branch.typedef.name () + " (" + Util.javaName (utype) + " discriminator, " + Util.javaStatefulName (branch.typedef) + " value)");
 502       stream.println ("  public void " + branch.typedef.name () + " (" + Util.javaName (utype) + " discriminator, " + Util.javaName (branch.typedef) + " value)");
 503       stream.println ("  {");
 504       stream.println ("    verify" + branch.typedef.name () + " (discriminator);");
 505       stream.println ("    __discriminator = discriminator;");
 506       stream.println ("    ___" + branch.typedef.name () + " = value;");
 507       stream.println ("    __uninitialized = false;");
 508       stream.println ("  }");
 509     }
 510 
 511     // Write verifyXXX
 512     stream.println ();
 513     stream.println ("  private void verify" + branch.typedef.name () + " (" + Util.javaName (utype) + " discriminator)");
 514     stream.println ("  {");
 515 
 516     boolean onlyOne = true;
 517 
 518     if (branch.isDefault && u.branches ().size () == 1)
 519       ;// If all that is in this union is a default branch,
 520       // all discriminators are legal.  Don't print any
 521       // body to this method in that case.
 522     else
 523     {
 524       // Otherwise this code is executed and a body is printed.
 525       stream.print ("    if (");
 526       if (branch.isDefault)
 527       {
 528         Enumeration eBranches = u.branches ().elements ();
 529         while (eBranches.hasMoreElements ())
 530         {
 531           UnionBranch b = (UnionBranch)eBranches.nextElement ();
 532           if (b != branch)
 533           {
 534             Enumeration eLabels = b.labels.elements ();
 535             while (eLabels.hasMoreElements ())
 536             {
 537               Expression label = (Expression)eLabels.nextElement ();
 538               if (!onlyOne)
 539                 stream.print (" || ");
 540               if (unionIsEnum)
 541                 stream.print ("discriminator == " + typePackage + Util.parseExpression (label));
 542               else
 543                 stream.print ("discriminator == " + Util.parseExpression (label));
 544               onlyOne = false;
 545             }
 546           }
 547         }
 548       }
 549       else
 550       {
 551         Enumeration e = branch.labels.elements ();
 552         while (e.hasMoreElements ())
 553         {
 554           Expression label = (Expression)e.nextElement ();
 555           if (!onlyOne)
 556             stream.print (" && ");
 557           if (unionIsEnum)
 558             stream.print ("discriminator != " + typePackage + Util.parseExpression (label));
 559           else
 560             stream.print ("discriminator != " + Util.parseExpression (label));
 561           onlyOne = false;
 562         }
 563       }
 564       stream.println (")");
 565       stream.println ("      throw new org.omg.CORBA.BAD_OPERATION ();");
 566     }
 567     stream.println ("  }");
 568   } // writeBranchMethods
 569 
 570   ///////////////
 571   // From JavaGenerator
 572 
 573   /**
 574    *
 575    **/
 576 
 577   // Computes the total number of labels in the union, which is the sum
 578   // of the number of labels in each branch of the union.  Note that the
 579   // label for the default branch has size 0, but still counts in the total
 580   // size.
 581   private int unionLabelSize( UnionEntry un )
 582   {
 583     int size = 0 ;
 584     Vector branches = un.branches() ;
 585     for (int i = 0; i < branches.size (); ++i) {
 586         UnionBranch branch = (UnionBranch)(branches.get(i)) ;
 587         int branchSize = branch.labels.size() ;
 588         size += ((branchSize == 0) ? 1 : branchSize) ;
 589     }
 590     return size ;
 591   }
 592 
 593   public int helperType (int index, String indent, TCOffsets tcoffsets,
 594     String name, SymtabEntry entry, PrintWriter stream)
 595   {
 596     TCOffsets innerOffsets = new TCOffsets ();
 597     UnionEntry u = (UnionEntry)entry;
 598     String discTypeCode = "_disTypeCode" + index;
 599     String membersName = "_members" + index;
 600 
 601     // Build discriminator tc
 602     stream.println (indent + "org.omg.CORBA.TypeCode " + discTypeCode + ';');
 603     index = ((JavaGenerator)u.type ().generator ()).type (index + 1, indent,
 604         innerOffsets, discTypeCode, u.type (), stream);
 605     tcoffsets.bumpCurrentOffset (innerOffsets.currentOffset ());
 606 
 607     stream.println (indent + "org.omg.CORBA.UnionMember[] " + membersName +
 608         " = new org.omg.CORBA.UnionMember [" + unionLabelSize(u) + "];");
 609     String tcOfMembers = "_tcOf" + membersName;
 610     String anyOfMembers = "_anyOf" + membersName;
 611     stream.println (indent + "org.omg.CORBA.TypeCode " + tcOfMembers + ';');
 612     stream.println (indent + "org.omg.CORBA.Any " + anyOfMembers + ';');
 613 
 614     innerOffsets = new TCOffsets ();
 615     innerOffsets.set (entry);
 616     int offsetForUnion = innerOffsets.currentOffset ();
 617     for (int i = 0; i < u.branches ().size (); ++i) {
 618         UnionBranch branch = (UnionBranch)u.branches ().elementAt (i);
 619         TypedefEntry member = branch.typedef;
 620         Vector labels = branch.labels;
 621         String memberName = Util.stripLeadingUnderscores (member.name ());
 622 
 623         if (labels.size() == 0) {
 624             stream.println ();
 625             stream.println (indent + "// Branch for " + memberName +
 626                 " (Default case)" );
 627             SymtabEntry utype = Util.typeOf (u.type ());
 628             stream.println (indent + anyOfMembers + " = org.omg.CORBA.ORB.init ().create_any ();");
 629             // For default member, label is the zero octet (per CORBA spec.)
 630             stream.println (indent + anyOfMembers + ".insert_octet ((byte)0); // default member label");
 631 
 632             // Build typecode
 633             innerOffsets.bumpCurrentOffset (4); // label value
 634             index = ((JavaGenerator)member.generator ()).type (index, indent, innerOffsets, tcOfMembers, member, stream);
 635             int offsetSoFar = innerOffsets.currentOffset ();
 636             innerOffsets = new TCOffsets ();
 637             innerOffsets.set (entry);
 638             innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForUnion);
 639 
 640             // Build union member
 641             stream.println (indent + membersName + '[' + i + "] = new org.omg.CORBA.UnionMember (");
 642             stream.println (indent + "  \"" + memberName + "\",");
 643             stream.println (indent + "  " + anyOfMembers + ',');
 644             stream.println (indent + "  " + tcOfMembers + ',');
 645             stream.println (indent + "  null);");
 646         } else {
 647             Enumeration enumeration = labels.elements() ;
 648             while (enumeration.hasMoreElements()) {
 649                 Expression expr = (Expression)(enumeration.nextElement()) ;
 650                 String elem = Util.parseExpression( expr ) ;
 651 
 652                 stream.println ();
 653                 stream.println (indent + "// Branch for " + memberName +
 654                     " (case label " + elem + ")" );
 655 
 656                 SymtabEntry utype = Util.typeOf (u.type ());
 657 
 658                 // Build any
 659                 stream.println (indent + anyOfMembers + " = org.omg.CORBA.ORB.init ().create_any ();");
 660 
 661                 if (utype instanceof PrimitiveEntry)
 662                     stream.println (indent + anyOfMembers + ".insert_" +
 663                     Util.collapseName (utype.name ()) + " ((" + Util.javaName (utype) +
 664                         ')' + elem + ");");
 665                 else { // it must be enum
 666                     String enumClass = Util.javaName (utype);
 667                     stream.println (indent + Util.helperName (utype, false) + ".insert (" +
 668                         anyOfMembers + ", " + enumClass + '.' + elem + ");"); // <d61056>
 669                 }
 670 
 671                 // Build typecode
 672                 innerOffsets.bumpCurrentOffset (4); // label value
 673                 index = ((JavaGenerator)member.generator ()).type (index, indent, innerOffsets, tcOfMembers, member, stream);
 674                 int offsetSoFar = innerOffsets.currentOffset ();
 675                 innerOffsets = new TCOffsets ();
 676                 innerOffsets.set (entry);
 677                 innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForUnion);
 678 
 679                 // Build union member
 680                 stream.println (indent + membersName + '[' + i + "] = new org.omg.CORBA.UnionMember (");
 681                 stream.println (indent + "  \"" + memberName + "\",");
 682                 stream.println (indent + "  " + anyOfMembers + ',');
 683                 stream.println (indent + "  " + tcOfMembers + ',');
 684                 stream.println (indent + "  null);");
 685             }
 686         }
 687     }
 688 
 689     tcoffsets.bumpCurrentOffset (innerOffsets.currentOffset ());
 690 
 691     // Build create_union_tc
 692     stream.println (indent + name + " = org.omg.CORBA.ORB.init ().create_union_tc (" +
 693         Util.helperName (u, true) + ".id (), \"" + entry.name () + "\", " +
 694         discTypeCode + ", " + membersName + ");");
 695     return index;
 696   } // helperType
 697 
 698     public int type (int index, String indent, TCOffsets tcoffsets, String name,
 699         SymtabEntry entry, PrintWriter stream)
 700     {
 701         stream.println (indent + name + " = " + Util.helperName (entry, true) + ".type ();");
 702         return index;
 703     }
 704 
 705     public void helperRead (String entryName, SymtabEntry entry, PrintWriter stream)
 706     {
 707         stream.println ("    " + entryName + " value = new " + entryName + " ();");
 708         read (0, "    ", "value", entry, stream);
 709         stream.println ("    return value;");
 710     }
 711 
 712     public void helperWrite (SymtabEntry entry, PrintWriter stream)
 713     {
 714         write (0, "    ", "value", entry, stream);
 715     }
 716 
 717     public int read (int index, String indent, String name,
 718         SymtabEntry entry, PrintWriter stream)
 719     {
 720         UnionEntry u = (UnionEntry)entry;
 721         String disName = "_dis" + index++;
 722         SymtabEntry utype = Util.typeOf (u.type ());
 723         Util.writeInitializer (indent, disName, "", utype, stream);
 724 
 725         if (utype instanceof PrimitiveEntry)
 726             index = ((JavaGenerator)utype.generator ()).read (index, indent, disName, utype, stream);
 727         else
 728             stream.println (indent + disName + " = " + Util.helperName (utype, true) + ".read (istream);");
 729 
 730         if (utype.name ().equals ("boolean"))
 731             index = readBoolean (disName, index, indent, name, u, stream);
 732         else
 733             index = readNonBoolean (disName, index, indent, name, u, stream);
 734 
 735         return index;
 736     }
 737 
 738     private int readBoolean (String disName, int index, String indent,
 739         String name, UnionEntry u, PrintWriter stream)
 740     {
 741         UnionBranch firstBranch = (UnionBranch)u.branches ().firstElement ();
 742         UnionBranch secondBranch;
 743 
 744         if (u.branches ().size () == 2)
 745             secondBranch = (UnionBranch)u.branches ().lastElement ();
 746         else
 747             secondBranch = null;
 748 
 749         boolean firstBranchIsTrue = false;
 750         boolean noCases = false;
 751         try {
 752             if (u.branches ().size () == 1 &&
 753                 (u.defaultBranch () != null || firstBranch.labels.size () == 2)) {
 754                 noCases = true;
 755             } else {
 756                 Expression expr = (Expression)(firstBranch.labels.firstElement()) ;
 757                 Boolean bool = (Boolean)(expr.evaluate()) ;
 758                 firstBranchIsTrue = bool.booleanValue ();
 759             }
 760         } catch (EvaluationException ex) {
 761             // no action
 762         }
 763 
 764         if (noCases) {
 765             // There is only a default label.  Since there are no cases,
 766             // there is no need for if...else branches.
 767             index = readBranch (index, indent, firstBranch.typedef.name (), "",  firstBranch.typedef, stream);
 768         } else {
 769             // If first branch is false, swap branches
 770             if (!firstBranchIsTrue) {
 771                 UnionBranch tmp = firstBranch;
 772                 firstBranch = secondBranch;
 773                 secondBranch = tmp;
 774             }
 775 
 776             stream.println (indent + "if (" + disName + ')');
 777 
 778             if (firstBranch == null)
 779                 stream.println (indent + "  value._default(" + disName + ");");
 780             else {
 781                 stream.println (indent + '{');
 782                 index = readBranch (index, indent + "  ", firstBranch.typedef.name (),
 783                     disName, firstBranch.typedef, stream);
 784                 stream.println (indent + '}');
 785             }
 786 
 787             stream.println (indent + "else");
 788 
 789             if (secondBranch == null)
 790                 stream.println (indent + "  value._default(" + disName + ");");
 791             else {
 792                 stream.println (indent + '{');
 793                 index = readBranch (index, indent + "  ", secondBranch.typedef.name (),
 794                     disName, secondBranch.typedef, stream);
 795                 stream.println (indent + '}');
 796             }
 797         }
 798 
 799         return index;
 800     }
 801 
 802     private int readNonBoolean (String disName, int index, String indent,
 803         String name, UnionEntry u, PrintWriter stream)
 804     {
 805         SymtabEntry utype = Util.typeOf (u.type ());
 806 
 807         if (utype instanceof EnumEntry)
 808             stream.println (indent + "switch (" + disName + ".value ())");
 809         else
 810             stream.println (indent + "switch (" + disName + ')');
 811 
 812         stream.println (indent + '{');
 813         String typePackage = Util.javaQualifiedName (utype) + '.';
 814 
 815         Enumeration e = u.branches ().elements ();
 816         while (e.hasMoreElements ()) {
 817             UnionBranch branch = (UnionBranch)e.nextElement ();
 818             Enumeration labels = branch.labels.elements ();
 819 
 820             while (labels.hasMoreElements ()) {
 821                 Expression label = (Expression)labels.nextElement ();
 822 
 823                 if (utype instanceof EnumEntry) {
 824                     String key = Util.parseExpression (label);
 825                     stream.println (indent + "  case " + typePackage + '_' + key + ':');
 826                 } else
 827                     stream.println (indent + "  case " + cast (label, utype) + ':');
 828             }
 829 
 830             if (!branch.typedef.equals (u.defaultBranch ())) {
 831                 index = readBranch (index, indent + "    ", branch.typedef.name (),
 832                     branch.labels.size() > 1 ? disName : "" ,
 833                     branch.typedef, stream);
 834                 stream.println (indent + "    break;");
 835             }
 836         }
 837 
 838         // We need a default branch unless all of the case of the discriminator type
 839         // are listed in the case branches.
 840         if (!coversAll(u)) {
 841             stream.println( indent + "  default:") ;
 842 
 843             if (u.defaultBranch () == null) {
 844                 // If the union does not have a default branch, we still need to initialize
 845                 // the discriminator.
 846                 stream.println( indent + "    value._default( " + disName + " ) ;" ) ;
 847             } else {
 848                 index = readBranch (index, indent + "    ", u.defaultBranch ().name (), disName,
 849                     u.defaultBranch (), stream);
 850             }
 851 
 852             stream.println (indent + "    break;");
 853         }
 854 
 855         stream.println (indent + '}');
 856 
 857         return index;
 858     }
 859 
 860     private int readBranch (int index, String indent, String name, String disName, TypedefEntry entry, PrintWriter stream)
 861     {
 862         SymtabEntry type = entry.type ();
 863         Util.writeInitializer (indent, '_' + name, "", entry, stream);
 864 
 865         if (!entry.arrayInfo ().isEmpty () ||
 866             type instanceof SequenceEntry ||
 867             type instanceof PrimitiveEntry ||
 868             type instanceof StringEntry) {
 869             index = ((JavaGenerator)entry.generator ()).read (index, indent, '_' + name, entry, stream);
 870         } else {
 871             stream.println (indent + '_' + name + " = " + Util.helperName (type, true) + ".read (istream);");
 872         }
 873 
 874         stream.print (indent + "value." + name + " (");
 875         if( disName == "" )
 876             stream.println("_" + name + ");");
 877         else
 878             stream.println(disName + ", " + "_" + name + ");");
 879 
 880         return index;
 881     }
 882 
 883   /**
 884    *
 885    **/
 886   public int write (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 887   {
 888     UnionEntry u = (UnionEntry)entry;
 889     SymtabEntry utype = Util.typeOf (u.type ());
 890     if (utype instanceof PrimitiveEntry)
 891       index = ((JavaGenerator)utype.generator ()).write (index, indent, name + ".discriminator ()", utype, stream);
 892     else
 893       stream.println (indent + Util.helperName (utype, true) + ".write (ostream, " + name + ".discriminator ());"); // <d61056>
 894     if (utype.name ().equals ("boolean"))
 895       index = writeBoolean (name + ".discriminator ()", index, indent, name, u, stream);
 896     else
 897       index = writeNonBoolean (name + ".discriminator ()", index, indent, name, u, stream);
 898     return index;
 899   } // write
 900 
 901   /**
 902    *
 903    **/
 904   private int writeBoolean (String disName, int index, String indent, String name, UnionEntry u, PrintWriter stream)
 905   {
 906     SymtabEntry utype = Util.typeOf (u.type ());
 907     UnionBranch firstBranch = (UnionBranch)u.branches ().firstElement ();
 908     UnionBranch secondBranch;
 909     if (u.branches ().size () == 2)
 910       secondBranch = (UnionBranch)u.branches ().lastElement ();
 911     else
 912       secondBranch = null;
 913     boolean firstBranchIsTrue = false;
 914     boolean noCases = false;
 915     try
 916     {
 917       if (u.branches ().size () == 1 && (u.defaultBranch () != null || firstBranch.labels.size () == 2))
 918         noCases = true;
 919       else
 920         firstBranchIsTrue = ((Boolean)((Expression)firstBranch.labels.firstElement ()).evaluate ()).booleanValue ();
 921     }
 922     catch (EvaluationException ex)
 923     {}
 924 
 925     if (noCases)
 926     {
 927       // There is only a default label.  Since there are no cases,
 928       // there is no need for if...else branches.
 929       index = writeBranch (index, indent, name, firstBranch.typedef, stream);
 930     }
 931     else
 932     {
 933       // If first branch is false, swap branches
 934       if (!firstBranchIsTrue)
 935       {
 936         UnionBranch tmp = firstBranch;
 937         firstBranch = secondBranch;
 938         secondBranch = tmp;
 939       }
 940       if (firstBranch != null && secondBranch != null) {
 941           stream.println (indent + "if (" + disName + ')');
 942           stream.println (indent + '{');
 943           index = writeBranch (index, indent + "  ", name, firstBranch.typedef, stream);
 944           stream.println (indent + '}');
 945           stream.println (indent + "else");
 946           stream.println (indent + '{');
 947           index = writeBranch (index, indent + "  ", name, secondBranch.typedef, stream);
 948           stream.println (indent + '}');
 949       } else if (firstBranch != null) {
 950           stream.println (indent + "if (" + disName + ')');
 951           stream.println (indent + '{');
 952           index = writeBranch (index, indent + "  ", name, firstBranch.typedef, stream);
 953           stream.println (indent + '}');
 954       } else {
 955           stream.println (indent + "if (!" + disName + ')');
 956           stream.println (indent + '{');
 957           index = writeBranch (index, indent + "  ", name, secondBranch.typedef, stream);
 958           stream.println (indent + '}');
 959       }
 960     }
 961     return index;
 962   } // writeBoolean
 963 
 964   /**
 965    *
 966    **/
 967   private int writeNonBoolean (String disName, int index, String indent, String name, UnionEntry u, PrintWriter stream)
 968   {
 969     SymtabEntry utype = Util.typeOf (u.type ());
 970     if (utype instanceof EnumEntry)
 971       stream.println (indent + "switch (" + name + ".discriminator ().value ())");
 972     else
 973       stream.println (indent + "switch (" + name + ".discriminator ())");
 974     stream.println (indent + "{");
 975     String typePackage = Util.javaQualifiedName (utype) + '.';
 976     Enumeration e = u.branches ().elements ();
 977     while (e.hasMoreElements ())
 978     {
 979       UnionBranch branch = (UnionBranch)e.nextElement ();
 980       Enumeration labels = branch.labels.elements ();
 981       while (labels.hasMoreElements ())
 982       {
 983         Expression label = (Expression)labels.nextElement ();
 984         if (utype instanceof EnumEntry)
 985         {
 986           String key = Util.parseExpression (label);
 987           stream.println (indent + "  case " + typePackage + '_' + key + ":");
 988         }
 989         else
 990           stream.println (indent + "  case " + cast (label, utype) + ':');
 991       }
 992       if (!branch.typedef.equals (u.defaultBranch ()))
 993       {
 994         index = writeBranch (index, indent + "    ", name, branch.typedef, stream);
 995         stream.println (indent + "    break;");
 996       }
 997     }
 998     if (u.defaultBranch () != null) {
 999       stream.println (indent + "  default:");
1000       index = writeBranch (index, indent + "    ", name, u.defaultBranch (), stream);
1001       stream.println (indent + "    break;");
1002     }
1003     stream.println (indent + "}");
1004     return index;
1005   } // writeNonBoolean
1006 
1007   /**
1008    *
1009    **/
1010   private int writeBranch (int index, String indent, String name, TypedefEntry entry, PrintWriter stream)
1011   {
1012     SymtabEntry type = entry.type ();
1013     if (!entry.arrayInfo ().isEmpty () || type instanceof SequenceEntry || type instanceof PrimitiveEntry || type instanceof StringEntry)
1014       index = ((JavaGenerator)entry.generator ()).write (index, indent, name + '.' + entry.name () + " ()", entry, stream);
1015     else
1016       stream.println (indent + Util.helperName (type, true) + ".write (ostream, " + name + '.' + entry.name () + " ());"); // <d61056>
1017     return index;
1018   } // writeBranch
1019 
1020   // From JavaGenerator
1021   ///////////////
1022 
1023   /**
1024    *
1025    **/
1026   private String cast (Expression expr, SymtabEntry type)
1027   {
1028     String ret = Util.parseExpression (expr);
1029     if (type.name ().indexOf ("short") >= 0)
1030     {
1031       if (expr.value () instanceof Long)
1032       {
1033         long value = ((Long)expr.value ()).longValue ();
1034         if (value > Short.MAX_VALUE)
1035           ret = "(short)(" + ret + ')';
1036       }
1037       else if (expr.value () instanceof Integer)
1038       {
1039         int value = ((Integer)expr.value ()).intValue ();
1040         if (value > Short.MAX_VALUE)
1041           ret = "(short)(" + ret + ')';
1042       }
1043     }
1044     else if (type.name ().indexOf ("long") >= 0)
1045     {
1046       if (expr.value () instanceof Long)
1047       {
1048         long value = ((Long)expr.value ()).longValue ();
1049         // value == Integer.MIN_VALUE because if the number is
1050         // Integer.MIN_VALUE, then it will have the 'L' suffix and
1051         // the cast will be necessary.
1052         if (value > Integer.MAX_VALUE || value == Integer.MIN_VALUE)
1053           ret = "(int)(" + ret + ')';
1054       }
1055       else if (expr.value () instanceof Integer)
1056       {
1057         int value = ((Integer)expr.value ()).intValue ();
1058         // value == Integer.MIN_VALUE because if the number is
1059         // Integer.MIN_VALUE, then it will have the 'L' suffix and
1060         // the cast will be necessary.
1061         if (value > Integer.MAX_VALUE || value == Integer.MIN_VALUE)
1062           ret = "(int)(" + ret + ')';
1063       }
1064     }
1065     return ret;
1066   } // cast
1067 
1068   protected Hashtable   symbolTable = null;
1069   protected UnionEntry  u           = null;
1070   protected PrintWriter stream      = null;
1071   protected SymtabEntry utype       = null;
1072   protected boolean     unionIsEnum;
1073   protected String      typePackage = "";
1074 } // class UnionGen