UnionGen.java revision 608:7e06bf1dcb09
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
36package 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
45import java.io.File;
46import java.io.IOException;
47import java.io.PrintWriter;
48import java.util.Enumeration;
49import java.util.Hashtable;
50import java.util.Vector;
51
52import com.sun.tools.corba.se.idl.GenFileStream;
53import com.sun.tools.corba.se.idl.ConstEntry;
54import com.sun.tools.corba.se.idl.EnumEntry;
55import com.sun.tools.corba.se.idl.InterfaceEntry;
56import com.sun.tools.corba.se.idl.PrimitiveEntry;
57import com.sun.tools.corba.se.idl.SequenceEntry;
58import com.sun.tools.corba.se.idl.StringEntry;
59import com.sun.tools.corba.se.idl.SymtabEntry;
60import com.sun.tools.corba.se.idl.TypedefEntry;
61import com.sun.tools.corba.se.idl.UnionBranch;
62import com.sun.tools.corba.se.idl.UnionEntry;
63
64import com.sun.tools.corba.se.idl.constExpr.Expression;
65import com.sun.tools.corba.se.idl.constExpr.EvaluationException;
66
67/**
68 *
69 **/
70public 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
1075