blob: 89367e69ac29e34aed041a8a96c13014dbfffaef [file] [log] [blame]
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* COMPONENT_NAME: idl.toJava
*
* ORIGINS: 27
*
* Licensed Materials - Property of IBM
* 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
* RMI-IIOP v1.0
*
*/
package com.sun.tools.corba.se.idl.toJavaPortable;
// NOTES:
// -cast() does not support longlong types yet.
// -Deal with typedef changes.
// -Scoped names for the discriminator are ignored at the moment.
// -F46082.51<daz> Remove -stateful feature; javaStatefulName() obsolete.
// -D61056 <klr> Use Util.helperName
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import com.sun.tools.corba.se.idl.GenFileStream;
import com.sun.tools.corba.se.idl.ConstEntry;
import com.sun.tools.corba.se.idl.EnumEntry;
import com.sun.tools.corba.se.idl.InterfaceEntry;
import com.sun.tools.corba.se.idl.PrimitiveEntry;
import com.sun.tools.corba.se.idl.SequenceEntry;
import com.sun.tools.corba.se.idl.StringEntry;
import com.sun.tools.corba.se.idl.SymtabEntry;
import com.sun.tools.corba.se.idl.TypedefEntry;
import com.sun.tools.corba.se.idl.UnionBranch;
import com.sun.tools.corba.se.idl.UnionEntry;
import com.sun.tools.corba.se.idl.constExpr.Expression;
import com.sun.tools.corba.se.idl.constExpr.EvaluationException;
/**
*
**/
public class UnionGen implements com.sun.tools.corba.se.idl.UnionGen, JavaGenerator
{
/**
* Public zero-argument constructor.
**/
public UnionGen ()
{
} // ctor
/**
*
**/
public void generate (Hashtable symbolTable, UnionEntry u, PrintWriter s)
{
this.symbolTable = symbolTable;
this.u = u;
init ();
openStream ();
if (stream == null)
return;
generateHelper ();
generateHolder ();
writeHeading ();
writeBody ();
writeClosing ();
closeStream ();
generateContainedTypes ();
} // generate
/**
* Initialize members unique to this generator.
**/
protected void init ()
{
utype = Util.typeOf (u.type ());
unionIsEnum = utype instanceof EnumEntry;
} // init
/**
*
**/
protected void openStream ()
{
stream = Util.stream (u, ".java");
} // openStream
/**
*
**/
protected void generateHelper ()
{
((Factories)Compile.compiler.factories ()).helper ().generate (symbolTable, u);
} // generateHelper
/**
*
**/
protected void generateHolder ()
{
((Factories)Compile.compiler.factories ()).holder ().generate (symbolTable, u);
} // generateHolder
/**
*
**/
protected void writeHeading ()
{
// If the discriminator is an enum, assign the typePackage string.
if (unionIsEnum)
typePackage = Util.javaQualifiedName (utype) + '.';
else
typePackage = "";
Util.writePackage (stream, u);
Util.writeProlog (stream, ((GenFileStream)stream).name ());
String className = u.name ();
stream.println ("public final class " + u.name () + " implements org.omg.CORBA.portable.IDLEntity");
stream.println ("{");
} // writeHeading
/**
*
**/
protected void writeBody ()
{
// Write branches and populate quality arrays
int size = u.branches ().size () + 1;
Enumeration e = u.branches ().elements ();
int i = 0;
while (e.hasMoreElements ())
{
UnionBranch branch = (UnionBranch)e.nextElement ();
Util.fillInfo (branch.typedef);
// <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
//stream.println (" private " + Util.javaStatefulName (branch.typedef) + " ___" + branch.typedef.name () + ";");
stream.println (" private " + Util.javaName (branch.typedef) + " ___" + branch.typedef.name () + ";");
++i;
}
stream.println (" private " + Util.javaName (utype) + " __discriminator;");
stream.println (" private boolean __uninitialized = true;");
// Write ctor
stream.println ();
stream.println (" public " + u.name () + " ()");
stream.println (" {");
stream.println (" }");
// Write discriminator
stream.println ();
stream.println (" public " + Util.javaName (utype) + " " + safeName (u, "discriminator") + " ()");
stream.println (" {");
stream.println (" if (__uninitialized)");
stream.println (" throw new org.omg.CORBA.BAD_OPERATION ();");
stream.println (" return __discriminator;");
stream.println (" }");
// Write for each branch:
// - setter
// - getter
// - private verifyXXX
e = u.branches ().elements ();
i = 0;
while (e.hasMoreElements ())
{
UnionBranch branch = (UnionBranch)e.nextElement ();
writeBranchMethods (stream, u, branch, i++);
}
if (u.defaultBranch () == null && !coversAll (u))
{
stream.println ();
stream.println (" public void _default ()");
stream.println (" {");
stream.println (" __discriminator = " + defaultDiscriminator (u) + ';');
stream.println (" __uninitialized = false;");
stream.println (" }");
stream.println ();
stream.println (" public void _default (" + Util.javaName(utype) +
" discriminator)");
stream.println (" {");
stream.println (" verifyDefault( discriminator ) ;" );
stream.println (" __discriminator = discriminator ;");
stream.println (" __uninitialized = false;");
stream.println (" }");
writeVerifyDefault() ;
}
stream.println ();
} // writeBody
/**
*
**/
protected void writeClosing ()
{
stream.println ("} // class " + u.name ());
} // writeClosing
/**
*
**/
protected void closeStream ()
{
stream.close ();
} // closeStream
/**
*
**/
protected void generateContainedTypes ()
{
Enumeration e = u.contained ().elements ();
while (e.hasMoreElements ())
{
SymtabEntry entry = (SymtabEntry)e.nextElement ();
// Don't generate contained entries if they are sequences.
// Sequences are unnamed and since they translate to arrays,
// no classes are generated for them, not even holders in this
// case since they cannot be accessed outside of this union.
if (!(entry instanceof SequenceEntry))
entry.generate (symbolTable, stream);
}
} // generateContainedTypes
private void writeVerifyDefault()
{
Vector labels = vectorizeLabels (u.branches (), true);
if (Util.javaName(utype).equals ("boolean")) {
stream.println( "" ) ;
stream.println( " private void verifyDefault (boolean discriminator)" ) ;
stream.println( " {" ) ;
if (labels.contains ("true"))
stream.println (" if ( discriminator )");
else
stream.println (" if ( !discriminator )");
stream.println( " throw new org.omg.CORBA.BAD_OPERATION();" ) ;
stream.println( " }" ) ;
return;
}
stream.println( "" ) ;
stream.println( " private void verifyDefault( " + Util.javaName(utype) +
" value )" ) ;
stream.println( " {" ) ;
if (unionIsEnum)
stream.println( " switch (value.value()) {" ) ;
else
stream.println( " switch (value) {" ) ;
Enumeration e = labels.elements() ;
while (e.hasMoreElements()) {
String str = (String)(e.nextElement()) ;
stream.println( " case " + str + ":" ) ;
}
stream.println( " throw new org.omg.CORBA.BAD_OPERATION() ;" ) ;
stream.println( "" ) ;
stream.println( " default:" ) ;
stream.println( " return;" ) ;
stream.println( " }" ) ;
stream.println( " }" ) ;
}
private String defaultDiscriminator (UnionEntry u)
{
Vector labels = vectorizeLabels (u.branches (), false );
String ret = null;
SymtabEntry utype = Util.typeOf (u.type ());
if (utype instanceof PrimitiveEntry && utype.name ().equals ("boolean")) {
// If it got this far, then:
// - there is only one branch;
// - that branch has only one label.
if (labels.contains ("true"))
ret = "false";
else
ret = "true";
} else if (utype.name ().equals ("char")) {
// This doesn't handle '\u0030' == '0'. Unions are so
// seldom used. I don't have time to make this perfect.
int def = 0;
String string = "'\\u0000'";
while (def != 0xFFFF && labels.contains (string))
if (++def / 0x10 == 0)
string = "'\\u000" + def + "'";
else if (def / 0x100 == 0)
string = "\\u00" + def + "'";
else if (def / 0x1000 == 0)
string = "\\u0" + def + "'";
else
string = "\\u" + def + "'";
ret = string;
} else if (utype instanceof EnumEntry) {
Enumeration e = labels.elements ();
EnumEntry enumEntry = (EnumEntry)utype;
Vector enumList = (Vector)enumEntry.elements ().clone ();
// cull out those elements in the enumeration list that are
// in the cases of this union
while (e.hasMoreElements ())
enumList.removeElement (e.nextElement ());
// If all of the enum elements are covered in this union and
// there is a default statement, just pick one of the
// elements for the default. If there are enum elements
// which are NOT covered by the cases, pick one as the
// default.
if (enumList.size () == 0)
ret = typePackage + (String)enumEntry.elements ().lastElement ();
else
ret = typePackage + (String)enumList.firstElement ();
} else if (utype.name ().equals ("octet")) {
short def = Byte.MIN_VALUE;
while (def != Byte.MAX_VALUE && labels.contains (Integer.toString (def)))
++def;
ret = Integer.toString (def);
} else if (utype.name ().equals ("short")) {
short def = Short.MIN_VALUE;
while (def != Short.MAX_VALUE && labels.contains (Integer.toString (def)))
++def;
ret = Integer.toString (def);
} else if (utype.name ().equals ("long")) {
int def = Integer.MIN_VALUE;
while (def != Integer.MAX_VALUE && labels.contains (Integer.toString (def)))
++def;
ret = Integer.toString (def);
} else if (utype.name ().equals ("long long")) {
long def = Long.MIN_VALUE;
while (def != Long.MAX_VALUE && labels.contains (Long.toString (def)))
++def;
ret = Long.toString (def);
} else if (utype.name ().equals ("unsigned short")) {
short def = 0;
while (def != Short.MAX_VALUE && labels.contains (Integer.toString (def)))
++def;
ret = Integer.toString (def);
} else if (utype.name ().equals ("unsigned long")) {
int def = 0;
while (def != Integer.MAX_VALUE && labels.contains (Integer.toString (def)))
++def;
ret = Integer.toString (def);
} else if (utype.name ().equals ("unsigned long long")) {
long def = 0;
while (def != Long.MAX_VALUE && labels.contains (Long.toString (def)))
++def;
ret = Long.toString (def);
}
return ret;
} // defaultDiscriminator
/**
*
**/
private Vector vectorizeLabels (Vector branchVector, boolean useIntsForEnums )
{
Vector mergedLabels = new Vector ();
Enumeration branches = branchVector.elements ();
while (branches.hasMoreElements ())
{
UnionBranch branch = (UnionBranch)branches.nextElement ();
Enumeration labels = branch.labels.elements ();
while (labels.hasMoreElements ())
{
Expression expr = (Expression)labels.nextElement ();
String str ;
if (unionIsEnum)
if (useIntsForEnums)
str = typePackage + "_" + Util.parseExpression( expr ) ;
else
str = typePackage + Util.parseExpression( expr ) ;
else
str = Util.parseExpression( expr ) ;
mergedLabels.addElement (str);
}
}
return mergedLabels;
} // vectorizeLabels
/**
*
**/
private String safeName (UnionEntry u, String name)
{
Enumeration e = u.branches ().elements ();
while (e.hasMoreElements ())
if (((UnionBranch)e.nextElement ()).typedef.name ().equals (name))
{
name = '_' + name;
break;
}
return name;
} // safeName
/**
*
**/
private boolean coversAll (UnionEntry u)
{
// This assumes that it is not possible to cover types other than
// boolean and enums. This is not quite correct, but since octet
// is not a valid discriminator type, it's not too bad in practice.
// It may also be possible to cover a char type, but we won't worry
// about that either.
SymtabEntry utype = Util.typeOf (u.type ());
boolean coversAll = false;
if (utype.name ().equals ("boolean")) {
if (u.branches ().size () == 2)
coversAll = true;
} else if (utype instanceof EnumEntry) {
Vector labels = vectorizeLabels (u.branches (), true);
if (labels.size () == ((EnumEntry)utype).elements ().size ())
coversAll = true;
}
return coversAll;
} // coversAll
/**
*
**/
private void writeBranchMethods (PrintWriter stream, UnionEntry u, UnionBranch branch, int i)
{
// Write getter
stream.println ();
// <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
//stream.println (" public " + Util.javaStatefulName (branch.typedef) + " " + branch.typedef.name () + " ()");
stream.println (" public " + Util.javaName (branch.typedef) + " " + branch.typedef.name () + " ()");
stream.println (" {");
stream.println (" if (__uninitialized)");
stream.println (" throw new org.omg.CORBA.BAD_OPERATION ();");
stream.println (" verify" + branch.typedef.name () + " (__discriminator);");
stream.println (" return ___" + branch.typedef.name () + ";");
stream.println (" }");
// Write setter(s)
stream.println ();
// <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
//stream.println (" public void " + branch.typedef.name () + " (" + Util.javaStatefulName (branch.typedef) + " value)");
stream.println (" public void " + branch.typedef.name () + " (" + Util.javaName (branch.typedef) + " value)");
stream.println (" {");
if (branch.labels.size () == 0)
{
// This is a default branch
stream.println (" __discriminator = " + defaultDiscriminator (u) + ";");
}
else
{
// This is a non-default branch
if (unionIsEnum)
stream.println (" __discriminator = " + typePackage + Util.parseExpression ((Expression)branch.labels.firstElement ()) + ";");
else
stream.println (" __discriminator = " + cast ((Expression)branch.labels.firstElement (), u.type ()) + ";");
}
stream.println (" ___" + branch.typedef.name () + " = value;");
stream.println (" __uninitialized = false;");
stream.println (" }");
SymtabEntry utype = Util.typeOf (u.type ());
// If there are multiple labels for one branch, write the
// setter that takes a discriminator.
if (branch.labels.size () > 0 || branch.isDefault)
{
stream.println ();
// <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
//stream.println (" public void " + branch.typedef.name () + " (" + Util.javaName (utype) + " discriminator, " + Util.javaStatefulName (branch.typedef) + " value)");
stream.println (" public void " + branch.typedef.name () + " (" + Util.javaName (utype) + " discriminator, " + Util.javaName (branch.typedef) + " value)");
stream.println (" {");
stream.println (" verify" + branch.typedef.name () + " (discriminator);");
stream.println (" __discriminator = discriminator;");
stream.println (" ___" + branch.typedef.name () + " = value;");
stream.println (" __uninitialized = false;");
stream.println (" }");
}
// Write verifyXXX
stream.println ();
stream.println (" private void verify" + branch.typedef.name () + " (" + Util.javaName (utype) + " discriminator)");
stream.println (" {");
boolean onlyOne = true;
if (branch.isDefault && u.branches ().size () == 1)
;// If all that is in this union is a default branch,
// all discriminators are legal. Don't print any
// body to this method in that case.
else
{
// Otherwise this code is executed and a body is printed.
stream.print (" if (");
if (branch.isDefault)
{
Enumeration eBranches = u.branches ().elements ();
while (eBranches.hasMoreElements ())
{
UnionBranch b = (UnionBranch)eBranches.nextElement ();
if (b != branch)
{
Enumeration eLabels = b.labels.elements ();
while (eLabels.hasMoreElements ())
{
Expression label = (Expression)eLabels.nextElement ();
if (!onlyOne)
stream.print (" || ");
if (unionIsEnum)
stream.print ("discriminator == " + typePackage + Util.parseExpression (label));
else
stream.print ("discriminator == " + Util.parseExpression (label));
onlyOne = false;
}
}
}
}
else
{
Enumeration e = branch.labels.elements ();
while (e.hasMoreElements ())
{
Expression label = (Expression)e.nextElement ();
if (!onlyOne)
stream.print (" && ");
if (unionIsEnum)
stream.print ("discriminator != " + typePackage + Util.parseExpression (label));
else
stream.print ("discriminator != " + Util.parseExpression (label));
onlyOne = false;
}
}
stream.println (")");
stream.println (" throw new org.omg.CORBA.BAD_OPERATION ();");
}
stream.println (" }");
} // writeBranchMethods
///////////////
// From JavaGenerator
/**
*
**/
// Computes the total number of labels in the union, which is the sum
// of the number of labels in each branch of the union. Note that the
// label for the default branch has size 0, but still counts in the total
// size.
private int unionLabelSize( UnionEntry un )
{
int size = 0 ;
Vector branches = un.branches() ;
for (int i = 0; i < branches.size (); ++i) {
UnionBranch branch = (UnionBranch)(branches.get(i)) ;
int branchSize = branch.labels.size() ;
size += ((branchSize == 0) ? 1 : branchSize) ;
}
return size ;
}
public int helperType (int index, String indent, TCOffsets tcoffsets,
String name, SymtabEntry entry, PrintWriter stream)
{
TCOffsets innerOffsets = new TCOffsets ();
UnionEntry u = (UnionEntry)entry;
String discTypeCode = "_disTypeCode" + index;
String membersName = "_members" + index;
// Build discriminator tc
stream.println (indent + "org.omg.CORBA.TypeCode " + discTypeCode + ';');
index = ((JavaGenerator)u.type ().generator ()).type (index + 1, indent,
innerOffsets, discTypeCode, u.type (), stream);
tcoffsets.bumpCurrentOffset (innerOffsets.currentOffset ());
stream.println (indent + "org.omg.CORBA.UnionMember[] " + membersName +
" = new org.omg.CORBA.UnionMember [" + unionLabelSize(u) + "];");
String tcOfMembers = "_tcOf" + membersName;
String anyOfMembers = "_anyOf" + membersName;
stream.println (indent + "org.omg.CORBA.TypeCode " + tcOfMembers + ';');
stream.println (indent + "org.omg.CORBA.Any " + anyOfMembers + ';');
innerOffsets = new TCOffsets ();
innerOffsets.set (entry);
int offsetForUnion = innerOffsets.currentOffset ();
for (int i = 0; i < u.branches ().size (); ++i) {
UnionBranch branch = (UnionBranch)u.branches ().elementAt (i);
TypedefEntry member = branch.typedef;
Vector labels = branch.labels;
String memberName = Util.stripLeadingUnderscores (member.name ());
if (labels.size() == 0) {
stream.println ();
stream.println (indent + "// Branch for " + memberName +
" (Default case)" );
SymtabEntry utype = Util.typeOf (u.type ());
stream.println (indent + anyOfMembers + " = org.omg.CORBA.ORB.init ().create_any ();");
// For default member, label is the zero octet (per CORBA spec.)
stream.println (indent + anyOfMembers + ".insert_octet ((byte)0); // default member label");
// Build typecode
innerOffsets.bumpCurrentOffset (4); // label value
index = ((JavaGenerator)member.generator ()).type (index, indent, innerOffsets, tcOfMembers, member, stream);
int offsetSoFar = innerOffsets.currentOffset ();
innerOffsets = new TCOffsets ();
innerOffsets.set (entry);
innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForUnion);
// Build union member
stream.println (indent + membersName + '[' + i + "] = new org.omg.CORBA.UnionMember (");
stream.println (indent + " \"" + memberName + "\",");
stream.println (indent + " " + anyOfMembers + ',');
stream.println (indent + " " + tcOfMembers + ',');
stream.println (indent + " null);");
} else {
Enumeration enumeration = labels.elements() ;
while (enumeration.hasMoreElements()) {
Expression expr = (Expression)(enumeration.nextElement()) ;
String elem = Util.parseExpression( expr ) ;
stream.println ();
stream.println (indent + "// Branch for " + memberName +
" (case label " + elem + ")" );
SymtabEntry utype = Util.typeOf (u.type ());
// Build any
stream.println (indent + anyOfMembers + " = org.omg.CORBA.ORB.init ().create_any ();");
if (utype instanceof PrimitiveEntry)
stream.println (indent + anyOfMembers + ".insert_" +
Util.collapseName (utype.name ()) + " ((" + Util.javaName (utype) +
')' + elem + ");");
else { // it must be enum
String enumClass = Util.javaName (utype);
stream.println (indent + Util.helperName (utype, false) + ".insert (" +
anyOfMembers + ", " + enumClass + '.' + elem + ");"); // <d61056>
}
// Build typecode
innerOffsets.bumpCurrentOffset (4); // label value
index = ((JavaGenerator)member.generator ()).type (index, indent, innerOffsets, tcOfMembers, member, stream);
int offsetSoFar = innerOffsets.currentOffset ();
innerOffsets = new TCOffsets ();
innerOffsets.set (entry);
innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForUnion);
// Build union member
stream.println (indent + membersName + '[' + i + "] = new org.omg.CORBA.UnionMember (");
stream.println (indent + " \"" + memberName + "\",");
stream.println (indent + " " + anyOfMembers + ',');
stream.println (indent + " " + tcOfMembers + ',');
stream.println (indent + " null);");
}
}
}
tcoffsets.bumpCurrentOffset (innerOffsets.currentOffset ());
// Build create_union_tc
stream.println (indent + name + " = org.omg.CORBA.ORB.init ().create_union_tc (" +
Util.helperName (u, true) + ".id (), \"" + entry.name () + "\", " +
discTypeCode + ", " + membersName + ");");
return index;
} // helperType
public int type (int index, String indent, TCOffsets tcoffsets, String name,
SymtabEntry entry, PrintWriter stream)
{
stream.println (indent + name + " = " + Util.helperName (entry, true) + ".type ();");
return index;
}
public void helperRead (String entryName, SymtabEntry entry, PrintWriter stream)
{
stream.println (" " + entryName + " value = new " + entryName + " ();");
read (0, " ", "value", entry, stream);
stream.println (" return value;");
}
public void helperWrite (SymtabEntry entry, PrintWriter stream)
{
write (0, " ", "value", entry, stream);
}
public int read (int index, String indent, String name,
SymtabEntry entry, PrintWriter stream)
{
UnionEntry u = (UnionEntry)entry;
String disName = "_dis" + index++;
SymtabEntry utype = Util.typeOf (u.type ());
Util.writeInitializer (indent, disName, "", utype, stream);
if (utype instanceof PrimitiveEntry)
index = ((JavaGenerator)utype.generator ()).read (index, indent, disName, utype, stream);
else
stream.println (indent + disName + " = " + Util.helperName (utype, true) + ".read (istream);");
if (utype.name ().equals ("boolean"))
index = readBoolean (disName, index, indent, name, u, stream);
else
index = readNonBoolean (disName, index, indent, name, u, stream);
return index;
}
private int readBoolean (String disName, int index, String indent,
String name, UnionEntry u, PrintWriter stream)
{
UnionBranch firstBranch = (UnionBranch)u.branches ().firstElement ();
UnionBranch secondBranch;
if (u.branches ().size () == 2)
secondBranch = (UnionBranch)u.branches ().lastElement ();
else
secondBranch = null;
boolean firstBranchIsTrue = false;
boolean noCases = false;
try {
if (u.branches ().size () == 1 &&
(u.defaultBranch () != null || firstBranch.labels.size () == 2)) {
noCases = true;
} else {
Expression expr = (Expression)(firstBranch.labels.firstElement()) ;
Boolean bool = (Boolean)(expr.evaluate()) ;
firstBranchIsTrue = bool.booleanValue ();
}
} catch (EvaluationException ex) {
// no action
}
if (noCases) {
// There is only a default label. Since there are no cases,
// there is no need for if...else branches.
index = readBranch (index, indent, firstBranch.typedef.name (), "", firstBranch.typedef, stream);
} else {
// If first branch is false, swap branches
if (!firstBranchIsTrue) {
UnionBranch tmp = firstBranch;
firstBranch = secondBranch;
secondBranch = tmp;
}
stream.println (indent + "if (" + disName + ')');
if (firstBranch == null)
stream.println (indent + " value._default(" + disName + ");");
else {
stream.println (indent + '{');
index = readBranch (index, indent + " ", firstBranch.typedef.name (),
disName, firstBranch.typedef, stream);
stream.println (indent + '}');
}
stream.println (indent + "else");
if (secondBranch == null)
stream.println (indent + " value._default(" + disName + ");");
else {
stream.println (indent + '{');
index = readBranch (index, indent + " ", secondBranch.typedef.name (),
disName, secondBranch.typedef, stream);
stream.println (indent + '}');
}
}
return index;
}
private int readNonBoolean (String disName, int index, String indent,
String name, UnionEntry u, PrintWriter stream)
{
SymtabEntry utype = Util.typeOf (u.type ());
if (utype instanceof EnumEntry)
stream.println (indent + "switch (" + disName + ".value ())");
else
stream.println (indent + "switch (" + disName + ')');
stream.println (indent + '{');
String typePackage = Util.javaQualifiedName (utype) + '.';
Enumeration e = u.branches ().elements ();
while (e.hasMoreElements ()) {
UnionBranch branch = (UnionBranch)e.nextElement ();
Enumeration labels = branch.labels.elements ();
while (labels.hasMoreElements ()) {
Expression label = (Expression)labels.nextElement ();
if (utype instanceof EnumEntry) {
String key = Util.parseExpression (label);
stream.println (indent + " case " + typePackage + '_' + key + ':');
} else
stream.println (indent + " case " + cast (label, utype) + ':');
}
if (!branch.typedef.equals (u.defaultBranch ())) {
index = readBranch (index, indent + " ", branch.typedef.name (),
branch.labels.size() > 1 ? disName : "" ,
branch.typedef, stream);
stream.println (indent + " break;");
}
}
// We need a default branch unless all of the case of the discriminator type
// are listed in the case branches.
if (!coversAll(u)) {
stream.println( indent + " default:") ;
if (u.defaultBranch () == null) {
// If the union does not have a default branch, we still need to initialize
// the discriminator.
stream.println( indent + " value._default( " + disName + " ) ;" ) ;
} else {
index = readBranch (index, indent + " ", u.defaultBranch ().name (), disName,
u.defaultBranch (), stream);
}
stream.println (indent + " break;");
}
stream.println (indent + '}');
return index;
}
private int readBranch (int index, String indent, String name, String disName, TypedefEntry entry, PrintWriter stream)
{
SymtabEntry type = entry.type ();
Util.writeInitializer (indent, '_' + name, "", entry, stream);
if (!entry.arrayInfo ().isEmpty () ||
type instanceof SequenceEntry ||
type instanceof PrimitiveEntry ||
type instanceof StringEntry) {
index = ((JavaGenerator)entry.generator ()).read (index, indent, '_' + name, entry, stream);
} else {
stream.println (indent + '_' + name + " = " + Util.helperName (type, true) + ".read (istream);");
}
stream.print (indent + "value." + name + " (");
if( disName == "" )
stream.println("_" + name + ");");
else
stream.println(disName + ", " + "_" + name + ");");
return index;
}
/**
*
**/
public int write (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
{
UnionEntry u = (UnionEntry)entry;
SymtabEntry utype = Util.typeOf (u.type ());
if (utype instanceof PrimitiveEntry)
index = ((JavaGenerator)utype.generator ()).write (index, indent, name + ".discriminator ()", utype, stream);
else
stream.println (indent + Util.helperName (utype, true) + ".write (ostream, " + name + ".discriminator ());"); // <d61056>
if (utype.name ().equals ("boolean"))
index = writeBoolean (name + ".discriminator ()", index, indent, name, u, stream);
else
index = writeNonBoolean (name + ".discriminator ()", index, indent, name, u, stream);
return index;
} // write
/**
*
**/
private int writeBoolean (String disName, int index, String indent, String name, UnionEntry u, PrintWriter stream)
{
SymtabEntry utype = Util.typeOf (u.type ());
UnionBranch firstBranch = (UnionBranch)u.branches ().firstElement ();
UnionBranch secondBranch;
if (u.branches ().size () == 2)
secondBranch = (UnionBranch)u.branches ().lastElement ();
else
secondBranch = null;
boolean firstBranchIsTrue = false;
boolean noCases = false;
try
{
if (u.branches ().size () == 1 && (u.defaultBranch () != null || firstBranch.labels.size () == 2))
noCases = true;
else
firstBranchIsTrue = ((Boolean)((Expression)firstBranch.labels.firstElement ()).evaluate ()).booleanValue ();
}
catch (EvaluationException ex)
{}
if (noCases)
{
// There is only a default label. Since there are no cases,
// there is no need for if...else branches.
index = writeBranch (index, indent, name, firstBranch.typedef, stream);
}
else
{
// If first branch is false, swap branches
if (!firstBranchIsTrue)
{
UnionBranch tmp = firstBranch;
firstBranch = secondBranch;
secondBranch = tmp;
}
if (firstBranch != null && secondBranch != null) {
stream.println (indent + "if (" + disName + ')');
stream.println (indent + '{');
index = writeBranch (index, indent + " ", name, firstBranch.typedef, stream);
stream.println (indent + '}');
stream.println (indent + "else");
stream.println (indent + '{');
index = writeBranch (index, indent + " ", name, secondBranch.typedef, stream);
stream.println (indent + '}');
} else if (firstBranch != null) {
stream.println (indent + "if (" + disName + ')');
stream.println (indent + '{');
index = writeBranch (index, indent + " ", name, firstBranch.typedef, stream);
stream.println (indent + '}');
} else {
stream.println (indent + "if (!" + disName + ')');
stream.println (indent + '{');
index = writeBranch (index, indent + " ", name, secondBranch.typedef, stream);
stream.println (indent + '}');
}
}
return index;
} // writeBoolean
/**
*
**/
private int writeNonBoolean (String disName, int index, String indent, String name, UnionEntry u, PrintWriter stream)
{
SymtabEntry utype = Util.typeOf (u.type ());
if (utype instanceof EnumEntry)
stream.println (indent + "switch (" + name + ".discriminator ().value ())");
else
stream.println (indent + "switch (" + name + ".discriminator ())");
stream.println (indent + "{");
String typePackage = Util.javaQualifiedName (utype) + '.';
Enumeration e = u.branches ().elements ();
while (e.hasMoreElements ())
{
UnionBranch branch = (UnionBranch)e.nextElement ();
Enumeration labels = branch.labels.elements ();
while (labels.hasMoreElements ())
{
Expression label = (Expression)labels.nextElement ();
if (utype instanceof EnumEntry)
{
String key = Util.parseExpression (label);
stream.println (indent + " case " + typePackage + '_' + key + ":");
}
else
stream.println (indent + " case " + cast (label, utype) + ':');
}
if (!branch.typedef.equals (u.defaultBranch ()))
{
index = writeBranch (index, indent + " ", name, branch.typedef, stream);
stream.println (indent + " break;");
}
}
if (u.defaultBranch () != null) {
stream.println (indent + " default:");
index = writeBranch (index, indent + " ", name, u.defaultBranch (), stream);
stream.println (indent + " break;");
}
stream.println (indent + "}");
return index;
} // writeNonBoolean
/**
*
**/
private int writeBranch (int index, String indent, String name, TypedefEntry entry, PrintWriter stream)
{
SymtabEntry type = entry.type ();
if (!entry.arrayInfo ().isEmpty () || type instanceof SequenceEntry || type instanceof PrimitiveEntry || type instanceof StringEntry)
index = ((JavaGenerator)entry.generator ()).write (index, indent, name + '.' + entry.name () + " ()", entry, stream);
else
stream.println (indent + Util.helperName (type, true) + ".write (ostream, " + name + '.' + entry.name () + " ());"); // <d61056>
return index;
} // writeBranch
// From JavaGenerator
///////////////
/**
*
**/
private String cast (Expression expr, SymtabEntry type)
{
String ret = Util.parseExpression (expr);
if (type.name ().indexOf ("short") >= 0)
{
if (expr.value () instanceof Long)
{
long value = ((Long)expr.value ()).longValue ();
if (value > Short.MAX_VALUE)
ret = "(short)(" + ret + ')';
}
else if (expr.value () instanceof Integer)
{
int value = ((Integer)expr.value ()).intValue ();
if (value > Short.MAX_VALUE)
ret = "(short)(" + ret + ')';
}
}
else if (type.name ().indexOf ("long") >= 0)
{
if (expr.value () instanceof Long)
{
long value = ((Long)expr.value ()).longValue ();
// value == Integer.MIN_VALUE because if the number is
// Integer.MIN_VALUE, then it will have the 'L' suffix and
// the cast will be necessary.
if (value > Integer.MAX_VALUE || value == Integer.MIN_VALUE)
ret = "(int)(" + ret + ')';
}
else if (expr.value () instanceof Integer)
{
int value = ((Integer)expr.value ()).intValue ();
// value == Integer.MIN_VALUE because if the number is
// Integer.MIN_VALUE, then it will have the 'L' suffix and
// the cast will be necessary.
if (value > Integer.MAX_VALUE || value == Integer.MIN_VALUE)
ret = "(int)(" + ret + ')';
}
}
return ret;
} // cast
protected Hashtable symbolTable = null;
protected UnionEntry u = null;
protected PrintWriter stream = null;
protected SymtabEntry utype = null;
protected boolean unionIsEnum;
protected String typePackage = "";
} // class UnionGen