package org.jacorb.idl; /* * JacORB - a free Java ORB * * Copyright (C) 1997-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintWriter; import java.util.Enumeration; import java.util.Set; import java.util.logging.Level; /** * @author Gerald Brose */ public class UnionType extends TypeDeclaration implements Scope { /** the union's discriminator's type spec */ TypeSpec switch_type_spec; SwitchBody switch_body; private boolean written = false; private ScopeData scopeData; private boolean allCasesCovered = false; private boolean switch_is_enum = false; private boolean switch_is_bool = false; private boolean switch_is_longlong = false; private boolean explicit_default_case = false; private boolean isParsed = false; private int labels; public UnionType(int num) { super(num); pack_name = ""; } public Object clone() { UnionType ut = new UnionType(new_num()); ut.switch_type_spec = this.switch_type_spec; ut.switch_body = switch_body; ut.pack_name = this.pack_name; ut.name = this.name; ut.written = this.written; ut.scopeData = this.scopeData; ut.enclosing_symbol = this.enclosing_symbol; ut.token = this.token; return ut; } public void setScopeData(ScopeData data) { scopeData = data; } public ScopeData getScopeData() { return scopeData; } public TypeDeclaration declaration() { return this; } public void setEnclosingSymbol(IdlSymbol s) { if (enclosing_symbol != null && enclosing_symbol != s) throw new RuntimeException("Compiler Error: trying to reassign container for " + name); enclosing_symbol = s; if (switch_body != null) { switch_body.setEnclosingSymbol(s); } } public String typeName() { if (typeName == null) setPrintPhaseNames(); return typeName; } public String className() { String fullName = typeName(); if (fullName.indexOf('.') > 0) { return fullName.substring(fullName.lastIndexOf('.') + 1); } return fullName; } public String printReadExpression(String Streamname) { return typeName() + "Helper.read(" + Streamname + ")"; } public String printWriteStatement(String var_name, String streamname) { return typeName() + "Helper.write(" + streamname + "," + var_name + ");"; } public String holderName() { return typeName() + "Holder"; } public String helperName() { return typeName() + "Helper"; } public void set_included(boolean i) { included = i; } public void setSwitchType(TypeSpec s) { switch_type_spec = s; } public void setSwitchBody(SwitchBody sb) { switch_body = sb; } public void setPackage(String s) { s = parser.pack_replace(s); if (pack_name.length() > 0) { pack_name = s + "." + pack_name; } else { pack_name = s; } if (switch_type_spec != null) { switch_type_spec.setPackage (s); } if (switch_body != null) { switch_body.setPackage(s); } } public boolean basic() { return false; } public void parse() { if (isParsed) { // there are occasions where the compiler may try to parse // a union type spec for a second time, viz if the union is // referred to through a scoped name in another struct member. // that's not a problem, but we have to skip parsing again! return; } isParsed = true; boolean justAnotherOne = false; escapeName(); ConstrTypeSpec ctspec = new ConstrTypeSpec(new_num()); try { ScopedName.definePseudoScope(full_name()); ctspec.c_type_spec = this; NameTable.define(full_name(), IDLTypes.TYPE_UNION); TypeMap.typedef(full_name(), ctspec); } catch (NameAlreadyDefined nad) { Object forwardDeclaration = parser.get_pending (full_name ()); if (forwardDeclaration != null) { if (! (forwardDeclaration instanceof UnionType)) { parser.error("Forward declaration types mismatch for " + full_name() + ": name already defined with another type" , token); } if (switch_type_spec == null) { justAnotherOne = true; } // else actual definition if (!full_name().equals("org.omg.CORBA.TypeCode") && switch_type_spec != null) { TypeMap.replaceForwardDeclaration(full_name(), ctspec); } } else { parser.error("Union " + full_name() + " already defined", token); } } if (switch_type_spec != null) { // Resolve scoped names and aliases TypeSpec ts; if (switch_type_spec.type_spec instanceof ScopedName) { ts = ((ScopedName)switch_type_spec.type_spec).resolvedTypeSpec(); while(ts instanceof ScopedName || ts instanceof AliasTypeSpec) { if (ts instanceof ScopedName) { ts = ((ScopedName)ts).resolvedTypeSpec(); } else { ts = ((AliasTypeSpec)ts).originalType(); } } addImportedName(switch_type_spec.typeName()); } else { ts = switch_type_spec.type_spec; } // Check if we have a valid discriminator type if (!( ((ts instanceof SwitchTypeSpec) && (((SwitchTypeSpec)ts).isSwitchable())) || ((ts instanceof BaseType) && (((BaseType)ts).isSwitchType())) || ((ts instanceof ConstrTypeSpec) && (((ConstrTypeSpec)ts).c_type_spec instanceof EnumType)) )) { parser.error("Illegal Switch Type: " + ts.typeName(), token); } switch_type_spec.parse(); switch_body.setTypeSpec(switch_type_spec); switch_body.setUnion(this); ScopedName.addRecursionScope(typeName()); switch_body.parse(); ScopedName.removeRecursionScope(typeName()); NameTable.parsed_interfaces.put(full_name(), ""); parser.remove_pending(full_name()); } else if (!justAnotherOne) { // i am forward declared, must set myself as // pending further parsing parser.set_pending(full_name(), this); } } /** * @return a string for an expression of type TypeCode that * describes this type */ public String getTypeCodeExpression() { return typeName() + "Helper.type()"; } public String getTypeCodeExpression(Set knownTypes) { if (knownTypes.contains(this)) { return this.getRecursiveTypeCodeExpression(); } return this.getTypeCodeExpression(); } private void printUnionClass(String className, PrintWriter pw) { Enumeration e; if (!pack_name.equals("")) { pw.println("package " + pack_name + ";"); } printImport(pw); printClassComment("union", className, pw); pw.println("public" + parser.getFinalString() + " class " + className); pw.println("\timplements org.omg.CORBA.portable.IDLEntity"); pw.println("{"); TypeSpec ts = switch_type_spec.typeSpec(); while(ts instanceof ScopedName || ts instanceof AliasTypeSpec) { if (ts instanceof ScopedName) { ts = ((ScopedName)ts).resolvedTypeSpec(); } if (ts instanceof AliasTypeSpec) { ts = ((AliasTypeSpec)ts).originalType(); } } pw.println("\tprivate " + ts.typeName() + " discriminator;"); /* find a "default" value */ String defaultStr = ""; /* start by concatenating all case label lists into one list * (this list is used only for finding a default) */ int def = 0; java.util.Vector allCaseLabels = new java.util.Vector (); java.util.Vector unusedCaseLabels = new java.util.Vector (); e = switch_body.caseListVector.elements(); while (e.hasMoreElements()) { Case c = (Case)e.nextElement(); for (int i = 0; i < c.case_label_list.v.size(); i++) { labels++; // the overall number of labels is needed in a number of places... Object ce = c.case_label_list.v.elementAt(i); if (ce != null) { if (ce instanceof ConstExpr) { allCaseLabels.addElement(((ConstExpr)ce).toString()); } else { // this is a scoped name allCaseLabels.addElement (ScopedName.unPseudoName (((ScopedName)ce).resolvedName())); } } else { def = 1; explicit_default_case = true; } } } /* if switch type is an enum, the default is null */ if ((ts instanceof ConstrTypeSpec && ((ConstrTypeSpec)ts).declaration() instanceof EnumType)) { this.switch_is_enum = true; EnumType et = (EnumType)((ConstrTypeSpec)ts).declaration(); if (allCaseLabels.size() + def > et.size()) { lexer.emit_warn("Too many case labels in definition of union " + full_name() + ", default cannot apply", token); } if (allCaseLabels.size() + def == et.size()) { allCasesCovered = true; } for (int i = 0; i < et.size(); i++) { String qualifiedCaseLabel = ts.typeName() + "." + (String)et.enumlist.v.elementAt(i); if (!(allCaseLabels.contains(qualifiedCaseLabel))) { // Set default value to first unused case label if (defaultStr.length () == 0) { defaultStr = qualifiedCaseLabel; } unusedCaseLabels.addElement (qualifiedCaseLabel); } } } else { if (ts instanceof BaseType) { ts = ((BaseType)ts).typeSpec(); } if (ts instanceof BooleanType) { this.switch_is_bool = true; // find a "default" for boolean if (allCaseLabels.size() + def > 2) { parser.error("Case label error: too many default labels.", token); return; } else if (allCaseLabels.size() == 1) { if (((String)allCaseLabels.elementAt(0)).equals("true")) { defaultStr = "false"; } else { defaultStr = "true"; } } else { // labels for both true and false -> no default possible } } else if (ts instanceof CharType) { // find a "default" for char Enumeration enumeration; String charStr; boolean matched = false; short val; // Iterate through values until find on that is not a case value for (short s = 0; s < 256; s++) { matched = false; enumeration = allCaseLabels.elements (); while (enumeration.hasMoreElements ()) { charStr = (String) enumeration.nextElement (); // Remove quotes from char string 'x' charStr = charStr.substring (1, charStr.length () - 1); // Check if escaped value if (charStr.charAt (0) == '\\') { charStr = charStr.substring (1); val = Short.parseShort (charStr); } else { val = (short) charStr.charAt (0); } if (s == val) { matched = true; break; } continue; } // Current value does not match a case value so set as default if (! matched) { defaultStr = "(char)" + s; break; } } } else if (ts instanceof IntType) { int maxint = 65536; // 2^16, max short if (ts instanceof LongType) { maxint = 2147483647; // -2^31, max long } for (int i = 0; i < maxint; i++) { if (!(allCaseLabels.contains(String.valueOf(i)))) { defaultStr = Integer.toString(i); break; } } if (ts instanceof LongLongType) { this.switch_is_longlong = true; } } else { parser.logger.log(Level.SEVERE, "Something went wrong in UnionType, " + "could not identify switch type " + switch_type_spec.type_spec); } } /* print members */ e = switch_body.caseListVector.elements(); while (e.hasMoreElements()) { Case c = (Case)e.nextElement(); pw.println("\tprivate " + c.element_spec.typeSpec.typeName() + " " + c.element_spec.declarator.name() + ";"); } /* * print a constructor for class member initialization */ pw.println(Environment.NL + "\tpublic " + className + " ()"); pw.println("\t{"); pw.println("\t}" + Environment.NL); /* * print an accessor method for the discriminator */ pw.println("\tpublic " + ts.typeName() + " discriminator ()"); pw.println("\t{"); pw.println("\t\treturn discriminator;"); pw.println("\t}" + Environment.NL); /* * print accessor and modifiers for each case label and branch */ e = switch_body.caseListVector.elements(); while (e.hasMoreElements ()) { Case c = (Case) e.nextElement(); boolean thisCaseIsDefault = false; int caseLabelNum = c.case_label_list.v.size(); String label[] = new String[ caseLabelNum ]; /* make case labels available as strings */ for (int i = 0; i < caseLabelNum; i++) { Object o = c.case_label_list.v.elementAt(i); if (o == null) // null means "default" { label[ i ] = null; thisCaseIsDefault = true; } else if (o instanceof ConstExpr) { label[ i ] = ((ConstExpr)o).toString(); } else if (o instanceof ScopedName) { label[ i ] = ((ScopedName)o).typeName(); } } // accessors pw.println("\tpublic " + c.element_spec.typeSpec.typeName() + " " + c.element_spec.declarator.name() + " ()"); pw.println("\t{"); pw.print("\t\tif (discriminator != "); boolean defaultFound = false; for (int i = 0; i < caseLabelNum; i++) { if (label[ i ] == null) { defaultFound = true; pw.print (defaultStr); } else { pw.print (label[ i ]); } if (i < caseLabelNum - 1) { pw.print(" && discriminator != "); } } // Add checks for any unused case labels for default if (defaultFound) { for (int i = 0; i < unusedCaseLabels.size (); i++) { String lab = (String) unusedCaseLabels.elementAt (i); if (! lab.equals (defaultStr)) { pw.print (" && discriminator != " + lab); } } } pw.println(")" + Environment.NL + "\t\t\tthrow new org.omg.CORBA.BAD_OPERATION();"); pw.println("\t\treturn " + c.element_spec.declarator.name() + ";"); pw.println("\t}" + Environment.NL); // modifiers pw.println("\tpublic void " + c.element_spec.declarator.name() + " (" + c.element_spec.typeSpec.typeName() + " _x)"); pw.println("\t{"); pw.print("\t\tdiscriminator = "); if (label[ 0 ] == null) { pw.println(defaultStr + ";"); } else { pw.println(label[ 0 ] + ";"); } pw.println("\t\t" + c.element_spec.declarator.name() + " = _x;"); pw.println("\t}" + Environment.NL); if (caseLabelNum > 1 || thisCaseIsDefault) { pw.println("\tpublic void " + c.element_spec.declarator.name() + " (" + ts.typeName() + " _discriminator, " + c.element_spec.typeSpec.typeName() + " _x)"); pw.println("\t{"); pw.print("\t\tif (_discriminator != "); defaultFound = false; for (int i = 0; i < caseLabelNum; i++) { if (label[ i ] == null) { defaultFound = true; pw.print(defaultStr); } else { pw.print(label[ i ]); } if (i < caseLabelNum - 1) { pw.print(" && _discriminator != "); } } // Add checks for any unused case labels for default if (defaultFound) { for (int i = 0; i < unusedCaseLabels.size (); i++) { String lab = (String) unusedCaseLabels.elementAt (i); if (! lab.equals (defaultStr)) { pw.print (" && _discriminator != " + lab); } } } pw.println(")" + Environment.NL + "\t\t\tthrow new org.omg.CORBA.BAD_OPERATION();"); pw.println("\t\tdiscriminator = _discriminator;"); pw.println("\t\t" + c.element_spec.declarator.name() + " = _x;"); pw.println("\t}" + Environment.NL); } } if (parser.generateEnhanced) { printToString(className, pw, defaultStr); } /* if there is no default case and case labels do not cover * all discriminator values, we have to generate __defaultmethods */ if (def == 0 && defaultStr.length() > 0) { pw.println("\tpublic void __default ()"); pw.println("\t{"); pw.println("\t\tdiscriminator = " + defaultStr + ";"); pw.println("\t}"); pw.println("\tpublic void __default (" + ts.typeName() + " _discriminator)"); pw.println("\t{"); pw.print("\t\tif( "); for ( int i = 0; i < allCaseLabels.size (); i++ ) { String lab = (String) allCaseLabels.elementAt( i ); if (i == 0) { pw.print(" _discriminator == " + lab); } else { pw.print(" || _discriminator == " + lab); } } pw.println(" )" + Environment.NL + "\t\t\tthrow new org.omg.CORBA.BAD_PARAM( \"Illegal value is used in __default method\"," + " 34, org.omg.CORBA.CompletionStatus.COMPLETED_NO );" + Environment.NL); pw.println("\t\tdiscriminator = _discriminator;"); pw.println("\t}"); } pw.println("}"); } private void printToString(String s, PrintWriter pw, String defaultStr) { String indent1 = "\t\t\t"; String indent2 = "\t\t\t\t"; if (switch_is_longlong) { indent1 = "\t\t"; indent2 = "\t\t\t"; } String case_str = "case "; String colon_str = ":"; String default_str = "default:"; pw.println("\tpublic String toString()"); pw.println("\t{"); pw.println("\t\tfinal java.lang.StringBuffer _ret = new java.lang.StringBuffer();"); pw.print("\t\t_ret.append(\"union "); pw.print(s); pw.println(" {\");"); pw.println("\t\t_ret.append(\"\\n\");"); if (switch_is_enum) { pw.println ("\t\tswitch (discriminator.value ())"); pw.println ("\t\t{"); } else { if (switch_is_bool) { /* special case: booleans are no switch type in java */ case_str = "if (discriminator =="; colon_str = ")"; // colon_str and default_str are already set correctly } else if (switch_is_longlong) { pw.println ("\t\tlong disc = discriminator ;"); } else { pw.println ("\t\tswitch (discriminator )"); pw.println ("\t\t{"); } } UnionIterator ui = new UnionIterator (false) { protected String writeExpression(PrintWriter caseWriter, Case cse, int caseLabelNum, String indent2, Object o) { caseWriter.print("\t\t\t\t_ret.append("); caseWriter.print(cse.element_spec.declarator.name()); caseWriter.println(");"); // no "break" written for default case if (o != null && !switch_is_bool && !switch_is_longlong) { caseWriter.println (indent2 + "break;"); } if (switch_is_longlong) { caseWriter.println (indent2 + "return;"); } return null; } }; ui.iterate (pw, indent1, indent2, "", case_str, colon_str, default_str); pw.println("\t\t_ret.append(\"}\");"); pw.println("\t\treturn _ret.toString();"); pw.println("\t}"); pw.println(); } public void printHolderClass(String className, PrintWriter ps) { if (!pack_name.equals("")) { ps.println("package " + pack_name + ";"); } printClassComment("union", className, ps); ps.println("public" + parser.getFinalString() + " class " + className + "Holder"); ps.println("\timplements org.omg.CORBA.portable.Streamable"); ps.println("{"); ps.println("\tpublic " + className + " value;" + Environment.NL); ps.println("\tpublic " + className + "Holder ()"); ps.println("\t{"); ps.println("\t}"); ps.println("\tpublic " + className + "Holder (final " + className + " initial)"); ps.println("\t{"); ps.println("\t\tvalue = initial;"); ps.println("\t}"); ps.println("\tpublic org.omg.CORBA.TypeCode _type ()"); ps.println("\t{"); ps.println("\t\treturn " + className + "Helper.type ();"); ps.println("\t}"); ps.println("\tpublic void _read (final org.omg.CORBA.portable.InputStream in)"); ps.println("\t{"); ps.println("\t\tvalue = " + className + "Helper.read (in);"); ps.println("\t}"); ps.println("\tpublic void _write (final org.omg.CORBA.portable.OutputStream out)"); ps.println("\t{"); ps.println("\t\t" + className + "Helper.write (out, value);"); ps.println("\t}"); ps.println("}"); } private void printHelperClass (String className, PrintWriter ps) { if (!pack_name.equals ("")) { ps.println ("package " + pack_name + ";"); } printImport(ps); printClassComment("union", className, ps); ps.println("public abstract class " + className + "Helper"); ps.println("{"); ps.println("\tprivate volatile static org.omg.CORBA.TypeCode _type;"); ps.println("\tpublic static org.omg.CORBA.TypeCode type ()"); ps.println("\t{"); ps.println("\t\tif (_type == null)"); ps.println("\t\t{"); ps.println("\t\t\tsynchronized(" + name + "Helper.class)"); ps.println("\t\t\t{"); ps.println("\t\t\t\tif (_type == null)"); ps.println("\t\t\t\t{"); Enumeration e; Case cse; int caseLabelNum; ps.println("\t\t\torg.omg.CORBA.UnionMember[] members = new org.omg.CORBA.UnionMember[" + labels + "];"); ps.println("\t\t\torg.omg.CORBA.Any label_any;"); TypeSpec label_t = switch_type_spec.typeSpec(); if (label_t instanceof ScopedName) { label_t = ((ScopedName)label_t).resolvedTypeSpec(); } label_t = label_t.typeSpec(); e = switch_body.caseListVector.elements (); int mi = 0; while (e.hasMoreElements ()) { cse = (Case) e.nextElement(); TypeSpec t = cse.element_spec.typeSpec; if (t instanceof ScopedName) t = ((ScopedName)t).resolvedTypeSpec(); t = t.typeSpec(); Declarator d = cse.element_spec.declarator; caseLabelNum = cse.case_label_list.v.size(); for (int i = 0; i < caseLabelNum; i++) { Object o = cse.case_label_list.v.elementAt(i); ps.println("\t\t\tlabel_any = org.omg.CORBA.ORB.init().create_any ();"); TypeSpec tocheck = label_t; if (label_t instanceof AliasTypeSpec) { tocheck = ((AliasTypeSpec)label_t).originalType(); } if (o == null) { ps.println("\t\t\tlabel_any.insert_octet ((byte)0);"); } else if (tocheck instanceof BaseType) { if ((tocheck instanceof CharType) || (tocheck instanceof BooleanType) || (tocheck instanceof LongType) || (tocheck instanceof LongLongType)) { ps.print("\t\t\tlabel_any." + tocheck.printInsertExpression() + " (("); } else if (tocheck instanceof ShortType) { ps.print("\t\t\tlabel_any." + tocheck.printInsertExpression() + " ((short)("); } else { throw new RuntimeException("Compiler error: unrecognized BaseType: " + tocheck.typeName() + ":" + tocheck + ": " + tocheck.typeSpec() + ": " + tocheck.getClass().getName()); } ps.println(((ConstExpr)o) + "));"); } else if (switch_is_enum) { String _t = ((ScopedName)o).typeName(); ps.println("\t\t\t" + _t.substring(0, _t.lastIndexOf('.')) + "Helper.insert(label_any, " + _t + ");"); } else { throw new RuntimeException("Compiler error: unrecognized label type: " + tocheck.typeName()); } ps.print ( "\t\t\tmembers[" + (mi++) + "] = new org.omg.CORBA.UnionMember (\"" + d.deEscapeName() + "\", label_any, " ); if (t instanceof ConstrTypeSpec) { try { ps.print(t.typeSpec().helperName() + ".type(),"); } catch (NoHelperException ex) { ps.print(t.typeSpec().getTypeCodeExpression() + ","); } } else { ps.print(t.typeSpec().getTypeCodeExpression() + ","); } ps.println("null);"); } } ps.print("\t\t\t _type = org.omg.CORBA.ORB.init().create_union_tc(id(),\"" + className() + "\","); ps.println(switch_type_spec.typeSpec().getTypeCodeExpression() + ", members);"); ps.println("\t\t\t\t}"); ps.println("\t\t\t}"); ps.println("\t\t}"); ps.println("\t\t\treturn _type;"); ps.println("\t}" + Environment.NL); TypeSpec.printInsertExtractMethods(ps, typeName()); printIdMethod(ps); /** read method */ ps.println("\tpublic static " + className + " read (org.omg.CORBA.portable.InputStream in)"); ps.println("\t{"); if (parser.hasObjectCachePlugin()) { parser.getObjectCachePlugin().printCheckout(ps, className, "result"); parser.getObjectCachePlugin().printPreMemberRead(ps, this); } else { ps.println("\t\t" + className + " result = new " + className + "();"); } TypeSpec switch_ts_resolved = switch_type_spec; if (switch_type_spec.type_spec instanceof ScopedName) { switch_ts_resolved = ((ScopedName)switch_type_spec.type_spec).resolvedTypeSpec(); } String indent1 = "\t\t\t"; String indent2 = "\t\t\t\t"; String tryIndent = ""; if (switch_is_longlong) { indent1 = "\t\t"; indent2 = "\t\t\t"; } String case_str = "case "; String colon_str = ":"; String default_str = "default:"; if (switch_is_enum) { ps.println("\t\t" + switch_ts_resolved.toString() + " disc;"); if(explicit_default_case || !allCasesCovered) { tryIndent = "\t"; indent1 = "\t\t\t\t"; indent2 = "\t\t\t\t\t"; ps.println("\t\ttry"); ps.println("\t\t{"); } ps.println(tryIndent + "\t\tdisc = " + switch_ts_resolved.toString() + ".from_int(in.read_long());"); ps.println(tryIndent + "\t\tswitch (disc.value ())"); ps.println(tryIndent + "\t\t{"); } else { ps.println ("\t\t" + switch_ts_resolved.toString () + " " + switch_ts_resolved.printReadStatement ("disc", "in")); if (switch_is_bool) { /* special case: boolean is not a switch type in java */ case_str = "if (disc == "; colon_str = ")"; default_str = "else"; } else if (switch_is_longlong) { /* special case: long is not a switch type in java */ case_str = "if (disc == "; colon_str = ")"; default_str = "else"; } else { ps.println("\t\tswitch (disc)"); ps.println("\t\t{"); } } UnionIterator ui = new UnionIterator (true) { protected String writeExpression(PrintWriter caseWriter, Case cse, int caseLabelNum, String indent2, Object o) { ByteArrayOutputStream bosDef = new ByteArrayOutputStream (); PrintWriter bad_paramDefaultWriter = new PrintWriter (bosDef); TypeSpec t = cse.element_spec.typeSpec; Declarator d = cse.element_spec.declarator; String varname = "_var"; if (t instanceof ScopedName) { t = ((ScopedName)t).resolvedTypeSpec (); } t = t.typeSpec (); bad_paramDefaultWriter.println (indent2 + t.typeName () + " " + varname + ";"); bad_paramDefaultWriter.println (indent2 + t.printReadStatement (varname, "in")); bad_paramDefaultWriter.print (indent2 + "result." + d.name () + " ("); bad_paramDefaultWriter.close(); caseWriter.print(bosDef.toString()); if (caseLabelNum > 1) { caseWriter.print ("disc,"); } caseWriter.println (varname + ");"); // no "break" written for default case or for "if" construct if (o != null && !switch_is_bool && !switch_is_longlong) { caseWriter.println (indent2 + "break;"); } if (switch_is_longlong) { caseWriter.println (indent2 + "return result;"); } return bosDef.toString (); } }; ui.iterate (ps, indent1, indent2, "", case_str, colon_str, default_str); if (parser.hasObjectCachePlugin()) { parser.getObjectCachePlugin().printPostMemberRead(ps, this, "result"); } if (!switch_is_longlong) { ps.println ("\t\treturn result;"); } ps.println ("\t}"); if (parser.hasObjectCachePlugin()) { parser.getObjectCachePlugin().printCheckinHelper(ps, this); } /** write method */ ps.println ("\tpublic static void write (org.omg.CORBA.portable.OutputStream out, " + className + " s)"); ps.println ("\t{"); // Write out discriminator value plus start of switch statement if (switch_is_enum) { ps.println ("\t\tout.write_long (s.discriminator().value ());"); ps.println ("\t\tswitch (s.discriminator().value ())"); ps.println ("\t\t{"); } else { ps.println ("\t\t" + switch_type_spec.typeSpec().printWriteStatement("s.discriminator ()", "out")); if (switch_is_bool) { /* special case: booleans are no switch type in java */ case_str = "if (s.discriminator () == "; // colon_str and default_str are already set correctly } else if (switch_is_longlong) { ps.println ("\t\tlong disc = s.discriminator ();"); } else { ps.println ("\t\tswitch (s.discriminator ())"); ps.println ("\t\t{"); } } // Write out cases ui = new UnionIterator (false) { protected String writeExpression(PrintWriter caseWriter, Case cse, int caseLabelNum, String indent2, Object o) { TypeSpec t = cse.element_spec.typeSpec; Declarator d = cse.element_spec.declarator; if (t instanceof ScopedName) { t = ((ScopedName)t).resolvedTypeSpec (); } t = t.typeSpec (); caseWriter.println (indent2 + t.printWriteStatement ("s." + d.name () + " ()", "out")); // no "break" written for default case if (o != null && !switch_is_bool && !switch_is_longlong) { caseWriter.println (indent2 + "break;"); } if (switch_is_longlong) { caseWriter.println (indent2 + "return;"); } return null; } }; ui.iterate (ps, indent1, indent2, "", case_str, colon_str, default_str); ps.println ("\t}"); ps.println("}"); // end of helper class } /** generate required classes */ public void print(PrintWriter ps) { setPrintPhaseNames(); // no code generation for included definitions if (included && !generateIncluded()) return; // only write once if (!written) { // Forward declaration if (switch_type_spec != null) { try { // JAC570: when the enum declaration is used in union declaration // the following code will generate implementation classes for enum if (switch_type_spec.type_spec instanceof ConstrTypeSpec) { switch_type_spec.print(ps); } switch_body.print(ps); String className = className(); String path = parser.out_dir + fileSeparator + pack_name.replace('.', fileSeparator); File dir = new File(path); if (!dir.exists()) { if (!dir.mkdirs()) { org.jacorb.idl.parser.fatal_error("Unable to create " + path, null); } } String fname = className + ".java"; File f = new File(dir, fname); if (GlobalInputStream.isMoreRecentThan(f)) { // print the mapped java class PrintWriter printWriter = new PrintWriter(new java.io.FileWriter(f)); printUnionClass(className, printWriter); printWriter.close(); } fname = className + "Holder.java"; f = new File(dir, fname); if (GlobalInputStream.isMoreRecentThan(f)) { // print the holder class PrintWriter printWriter = new PrintWriter(new java.io.FileWriter(f)); printHolderClass(className, printWriter); printWriter.close(); } fname = className + "Helper.java"; f = new File(dir, fname); if (GlobalInputStream.isMoreRecentThan(f)) { // print the help class PrintWriter printWriter = new PrintWriter(new java.io.FileWriter(f)); printHelperClass(className, printWriter); printWriter.close(); } written = true; } catch (java.io.IOException i) { throw new RuntimeException("File IO error" + i); } } } } public void printInsertIntoAny(PrintWriter ps, String anyname, String varname) { ps.println("\t\t" + pack_name + "." + className() + "Helper.insert(" + anyname + ", " + varname + ");"); } public void printExtractResult(PrintWriter ps, String resultname, String anyname, String resulttype) { ps.println("\t\t" + resultname + " = " + className() + "Helper.extract(" + anyname + ");"); } public String toString() { return typeName(); } public void accept(IDLTreeVisitor visitor) { visitor.visitUnion(this); } public void set_name(String n) { super.set_name(n); boolean setpkg = (switch_type_spec != null && !(switch_type_spec.typeSpec() instanceof ScopedName)); // Don't override the package if this is a scopedname. if (setpkg) { switch_type_spec.setPackage( n ); } // As per above. if (switch_body != null && setpkg) { switch_body.setPackage( n ); } } private abstract class UnionIterator { boolean readExpression = false; UnionIterator(boolean writeExpression) { this.readExpression = writeExpression; } public void iterate(PrintWriter pw, String indent1, String indent2, String tryIndent, String case_str, String colon_str, String default_str) { Enumeration e; Case cse; ByteArrayOutputStream bos; PrintWriter caseWriter; boolean was_default = false; int caseCount = 0; int caseLabelNum; String defaultCases = null; String varname = "_var"; String bosDef = ""; if (switch_is_longlong) { indent1 = "\t\t"; indent2 = "\t\t\t"; } // Write out cases e = switch_body.caseListVector.elements (); while (e.hasMoreElements ()) { was_default = false; bos = new ByteArrayOutputStream (); caseWriter = new PrintWriter (bos); cse = (Case) e.nextElement (); caseLabelNum = cse.case_label_list.v.size (); Object o; for (int i = 0; i < caseLabelNum; i++) { o = cse.case_label_list.v.elementAt (i); caseCount++; if (o == null) { // null means "default" caseWriter.println (indent1 + default_str); was_default = true; } else if (o instanceof ConstExpr) { caseWriter.println (indent1 + case_str + ((ConstExpr)o) + colon_str); } else if (o instanceof ScopedName) { String _t = ((ScopedName)o).typeName (); if (switch_is_enum) { caseWriter.println (indent1 + case_str + _t.substring (0, _t.lastIndexOf ('.') + 1) + "_" + _t.substring (_t.lastIndexOf ('.') + 1) + colon_str); } else { caseWriter.println (indent1 + case_str + _t + colon_str); } } if (i == caseLabelNum - 1) { caseWriter.println (indent1 + "{"); bosDef = writeExpression (caseWriter, cse, caseLabelNum, indent2, o); caseWriter.println (indent1 + "}"); } } if (switch_is_bool && !was_default) { case_str = "else " + case_str; } // Print cases unless default caseWriter.close (); if (bos.size () > 0) { if (was_default) { defaultCases = bos.toString (); } else { pw.print (bos.toString ()); } } } if (readExpression) { if (switch_is_enum && (!explicit_default_case && !switch_is_bool && !switch_is_longlong && !allCasesCovered)) { pw.println (tryIndent + "\t\t\tdefault: result.__default (disc);"); } if (!explicit_default_case && switch_is_longlong) { pw.println ("\t\tresult.__default (disc);"); pw.println ("\t\treturn result;"); } // How can we have boolean with more than two cases? if (switch_is_bool && caseCount > 2) { System.err.println ("Case count is larger than two for a boolean expression"); throw new RuntimeException ("Case count is larger than two for a boolean expression"); } // If we have has boolean with one case then add a default. if (!explicit_default_case && switch_is_bool && caseCount != 2) { pw.println ("\t\t\telse"); pw.println ("\t\t\t{"); pw.println ("\t\t\t\tresult.__default (disc);"); pw.println ("\t\t\t}"); } } // Print out default cases last if (defaultCases != null) { pw.print (defaultCases); } /* close switch statement */ if (!switch_is_bool && !switch_is_longlong) { pw.println ("\t\t}"); } // close try if(readExpression && switch_is_enum && (explicit_default_case || !allCasesCovered)) { pw.println("\t\t}"); pw.println("\t\tcatch (org.omg.CORBA.BAD_PARAM b)"); pw.println("\t\t{"); pw.println("\t\t\t// The default value was out-of-bounds for the Enum. Just use the default."); if(was_default) { pw.print(bosDef); pw.println(varname + ");"); } else { pw.println("\t\t\tresult.__default ();"); } pw.println("\t\t}"); } } protected abstract String writeExpression(PrintWriter caseWriter, Case cse, int caseLabelNum, String indent2, Object o); } }