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    **/
UnionGen()75   public UnionGen ()
76   {
77   } // ctor
78 
79   /**
80    *
81    **/
generate(Hashtable symbolTable, UnionEntry u, PrintWriter s)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    **/
init()103   protected void init ()
104   {
105     utype       = Util.typeOf (u.type ());
106     unionIsEnum = utype instanceof EnumEntry;
107   } // init
108 
109   /**
110    *
111    **/
openStream()112   protected void openStream ()
113   {
114     stream = Util.stream (u, ".java");
115   } // openStream
116 
117   /**
118    *
119    **/
generateHelper()120   protected void generateHelper ()
121   {
122     ((Factories)Compile.compiler.factories ()).helper ().generate (symbolTable, u);
123   } // generateHelper
124 
125   /**
126    *
127    **/
generateHolder()128   protected void generateHolder ()
129   {
130    ((Factories)Compile.compiler.factories ()).holder ().generate (symbolTable, u);
131   } // generateHolder
132 
133   /**
134    *
135    **/
writeHeading()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    **/
writeBody()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    **/
writeClosing()225   protected void writeClosing ()
226   {
227     stream.println ("} // class " + u.name ());
228   } // writeClosing
229 
230   /**
231    *
232    **/
closeStream()233   protected void closeStream ()
234   {
235     stream.close ();
236   } // closeStream
237 
238   /**
239    *
240    **/
generateContainedTypes()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 
writeVerifyDefault()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 
defaultDiscriminator(UnionEntry u)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    **/
vectorizeLabels(Vector branchVector, boolean useIntsForEnums )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    **/
safeName(UnionEntry u, String name)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    **/
coversAll(UnionEntry u)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    **/
writeBranchMethods(PrintWriter stream, UnionEntry u, UnionBranch branch, int i)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.
unionLabelSize( UnionEntry un )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 
helperType(int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)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 
type(int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)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 
helperRead(String entryName, SymtabEntry entry, PrintWriter stream)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 
helperWrite(SymtabEntry entry, PrintWriter stream)712     public void helperWrite (SymtabEntry entry, PrintWriter stream)
713     {
714         write (0, "    ", "value", entry, stream);
715     }
716 
read(int index, String indent, String name, SymtabEntry entry, PrintWriter stream)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 
readBoolean(String disName, int index, String indent, String name, UnionEntry u, PrintWriter stream)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 
readNonBoolean(String disName, int index, String indent, String name, UnionEntry u, PrintWriter stream)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 
readBranch(int index, String indent, String name, String disName, TypedefEntry entry, PrintWriter stream)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    **/
write(int index, String indent, String name, SymtabEntry entry, PrintWriter stream)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    **/
writeBoolean(String disName, int index, String indent, String name, UnionEntry u, PrintWriter stream)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    **/
writeNonBoolean(String disName, int index, String indent, String name, UnionEntry u, PrintWriter stream)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    **/
writeBranch(int index, String indent, String name, TypedefEntry entry, PrintWriter stream)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    **/
cast(Expression expr, SymtabEntry type)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
1075