0001: /*
0002: * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025: /*
0026: * COMPONENT_NAME: idl.toJava
0027: *
0028: * ORIGINS: 27
0029: *
0030: * Licensed Materials - Property of IBM
0031: * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
0032: * RMI-IIOP v1.0
0033: *
0034: * @(#)UnionGen.java 1.10 01/01/09
0035: */
0036:
0037: package com.sun.tools.corba.se.idl.toJavaPortable;
0038:
0039: // NOTES:
0040: // -cast() does not support longlong types yet.
0041: // -Deal with typedef changes.
0042: // -Scoped names for the discriminator are ignored at the moment.
0043: // -F46082.51<daz> Remove -stateful feature; javaStatefulName() obsolete.
0044: // -D61056 <klr> Use Util.helperName
0045:
0046: import java.io.File;
0047: import java.io.IOException;
0048: import java.io.PrintWriter;
0049: import java.util.Enumeration;
0050: import java.util.Hashtable;
0051: import java.util.Vector;
0052:
0053: import com.sun.tools.corba.se.idl.GenFileStream;
0054: import com.sun.tools.corba.se.idl.ConstEntry;
0055: import com.sun.tools.corba.se.idl.EnumEntry;
0056: import com.sun.tools.corba.se.idl.InterfaceEntry;
0057: import com.sun.tools.corba.se.idl.PrimitiveEntry;
0058: import com.sun.tools.corba.se.idl.SequenceEntry;
0059: import com.sun.tools.corba.se.idl.StringEntry;
0060: import com.sun.tools.corba.se.idl.SymtabEntry;
0061: import com.sun.tools.corba.se.idl.TypedefEntry;
0062: import com.sun.tools.corba.se.idl.UnionBranch;
0063: import com.sun.tools.corba.se.idl.UnionEntry;
0064:
0065: import com.sun.tools.corba.se.idl.constExpr.Expression;
0066: import com.sun.tools.corba.se.idl.constExpr.EvaluationException;
0067:
0068: /**
0069: *
0070: **/
0071: public class UnionGen implements com.sun.tools.corba.se.idl.UnionGen,
0072: JavaGenerator {
0073: /**
0074: * Public zero-argument constructor.
0075: **/
0076: public UnionGen() {
0077: } // ctor
0078:
0079: /**
0080: *
0081: **/
0082: public void generate(Hashtable symbolTable, UnionEntry u,
0083: PrintWriter s) {
0084: this .symbolTable = symbolTable;
0085: this .u = u;
0086: init();
0087:
0088: openStream();
0089: if (stream == null)
0090: return;
0091: generateHelper();
0092: generateHolder();
0093: writeHeading();
0094: writeBody();
0095: writeClosing();
0096: closeStream();
0097: generateContainedTypes();
0098: } // generate
0099:
0100: /**
0101: * Initialize members unique to this generator.
0102: **/
0103: protected void init() {
0104: utype = Util.typeOf(u.type());
0105: unionIsEnum = utype instanceof EnumEntry;
0106: } // init
0107:
0108: /**
0109: *
0110: **/
0111: protected void openStream() {
0112: stream = Util.stream(u, ".java");
0113: } // openStream
0114:
0115: /**
0116: *
0117: **/
0118: protected void generateHelper() {
0119: ((Factories) Compile.compiler.factories()).helper().generate(
0120: symbolTable, u);
0121: } // generateHelper
0122:
0123: /**
0124: *
0125: **/
0126: protected void generateHolder() {
0127: ((Factories) Compile.compiler.factories()).holder().generate(
0128: symbolTable, u);
0129: } // generateHolder
0130:
0131: /**
0132: *
0133: **/
0134: protected void writeHeading() {
0135: // If the discriminator is an enum, assign the typePackage string.
0136: if (unionIsEnum)
0137: typePackage = Util.javaQualifiedName(utype) + '.';
0138: else
0139: typePackage = "";
0140:
0141: Util.writePackage(stream, u);
0142: Util.writeProlog(stream, ((GenFileStream) stream).name());
0143:
0144: String className = u.name();
0145: stream.println("public final class " + u.name()
0146: + " implements org.omg.CORBA.portable.IDLEntity");
0147: stream.println("{");
0148: } // writeHeading
0149:
0150: /**
0151: *
0152: **/
0153: protected void writeBody() {
0154: // Write branches and populate quality arrays
0155: int size = u.branches().size() + 1;
0156: Enumeration e = u.branches().elements();
0157: int i = 0;
0158: while (e.hasMoreElements()) {
0159: UnionBranch branch = (UnionBranch) e.nextElement();
0160: Util.fillInfo(branch.typedef);
0161: // <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
0162: //stream.println (" private " + Util.javaStatefulName (branch.typedef) + " ___" + branch.typedef.name () + ";");
0163: stream.println(" private " + Util.javaName(branch.typedef)
0164: + " ___" + branch.typedef.name() + ";");
0165: ++i;
0166: }
0167: stream.println(" private " + Util.javaName(utype)
0168: + " __discriminator;");
0169: stream.println(" private boolean __uninitialized = true;");
0170:
0171: // Write ctor
0172: stream.println();
0173: stream.println(" public " + u.name() + " ()");
0174: stream.println(" {");
0175: stream.println(" }");
0176:
0177: // Write discriminator
0178: stream.println();
0179: stream.println(" public " + Util.javaName(utype) + " "
0180: + safeName(u, "discriminator") + " ()");
0181: stream.println(" {");
0182: stream.println(" if (__uninitialized)");
0183: stream
0184: .println(" throw new org.omg.CORBA.BAD_OPERATION ();");
0185: stream.println(" return __discriminator;");
0186: stream.println(" }");
0187:
0188: // Write for each branch:
0189: // - setter
0190: // - getter
0191: // - private verifyXXX
0192: e = u.branches().elements();
0193: i = 0;
0194: while (e.hasMoreElements()) {
0195: UnionBranch branch = (UnionBranch) e.nextElement();
0196: writeBranchMethods(stream, u, branch, i++);
0197: }
0198: if (u.defaultBranch() == null && !coversAll(u)) {
0199: stream.println();
0200: stream.println(" public void _default ()");
0201: stream.println(" {");
0202: stream.println(" __discriminator = "
0203: + defaultDiscriminator(u) + ';');
0204: stream.println(" __uninitialized = false;");
0205: stream.println(" }");
0206:
0207: stream.println();
0208: stream.println(" public void _default ("
0209: + Util.javaName(utype) + " discriminator)");
0210: stream.println(" {");
0211: stream.println(" verifyDefault( discriminator ) ;");
0212: stream.println(" __discriminator = discriminator ;");
0213: stream.println(" __uninitialized = false;");
0214: stream.println(" }");
0215:
0216: writeVerifyDefault();
0217: }
0218: stream.println();
0219: } // writeBody
0220:
0221: /**
0222: *
0223: **/
0224: protected void writeClosing() {
0225: stream.println("} // class " + u.name());
0226: } // writeClosing
0227:
0228: /**
0229: *
0230: **/
0231: protected void closeStream() {
0232: stream.close();
0233: } // closeStream
0234:
0235: /**
0236: *
0237: **/
0238: protected void generateContainedTypes() {
0239: Enumeration e = u.contained().elements();
0240: while (e.hasMoreElements()) {
0241: SymtabEntry entry = (SymtabEntry) e.nextElement();
0242:
0243: // Don't generate contained entries if they are sequences.
0244: // Sequences are unnamed and since they translate to arrays,
0245: // no classes are generated for them, not even holders in this
0246: // case since they cannot be accessed outside of this union.
0247: if (!(entry instanceof SequenceEntry))
0248: entry.generate(symbolTable, stream);
0249: }
0250: } // generateContainedTypes
0251:
0252: private void writeVerifyDefault() {
0253: Vector labels = vectorizeLabels(u.branches(), true);
0254:
0255: stream.println("");
0256: stream.println(" private void verifyDefault( "
0257: + Util.javaName(utype) + " value )");
0258: stream.println(" {");
0259:
0260: if (unionIsEnum)
0261: stream.println(" switch (value.value()) {");
0262: else
0263: stream.println(" switch (value) {");
0264:
0265: Enumeration e = labels.elements();
0266: while (e.hasMoreElements()) {
0267: String str = (String) (e.nextElement());
0268: stream.println(" case " + str + ":");
0269: }
0270:
0271: stream
0272: .println(" throw new org.omg.CORBA.BAD_OPERATION() ;");
0273: stream.println("");
0274: stream.println(" default:");
0275: stream.println(" return;");
0276: stream.println(" }");
0277: stream.println(" }");
0278: }
0279:
0280: private String defaultDiscriminator(UnionEntry u) {
0281: Vector labels = vectorizeLabels(u.branches(), false);
0282: String ret = null;
0283: SymtabEntry utype = Util.typeOf(u.type());
0284: if (utype instanceof PrimitiveEntry
0285: && utype.name().equals("boolean")) {
0286: // If it got this far, then:
0287: // - there is only one branch;
0288: // - that branch has only one label.
0289: if (labels.contains("true"))
0290: ret = "false";
0291: else
0292: ret = "true";
0293: } else if (utype.name().equals("char")) {
0294: // This doesn't handle '\u0030' == '0'. Unions are so
0295: // seldom used. I don't have time to make this perfect.
0296: int def = 0;
0297: String string = "'\\u0000'";
0298: while (def != 0xFFFF && labels.contains(string))
0299: if (++def / 0x10 == 0)
0300: string = "'\\u000" + def + "'";
0301: else if (def / 0x100 == 0)
0302: string = "\\u00" + def + "'";
0303: else if (def / 0x1000 == 0)
0304: string = "\\u0" + def + "'";
0305: else
0306: string = "\\u" + def + "'";
0307: ret = string;
0308: } else if (utype instanceof EnumEntry) {
0309: Enumeration e = labels.elements();
0310: EnumEntry enumEntry = (EnumEntry) utype;
0311: Vector enumList = (Vector) enumEntry.elements().clone();
0312: // cull out those elements in the enumeration list that are
0313: // in the cases of this union
0314: while (e.hasMoreElements())
0315: enumList.removeElement(e.nextElement());
0316: // If all of the enum elements are covered in this union and
0317: // there is a default statement, just pick one of the
0318: // elements for the default. If there are enum elements
0319: // which are NOT covered by the cases, pick one as the
0320: // default.
0321: if (enumList.size() == 0)
0322: ret = typePackage
0323: + (String) enumEntry.elements().lastElement();
0324: else
0325: ret = typePackage + (String) enumList.firstElement();
0326: } else if (utype.name().equals("octet")) {
0327: short def = Byte.MIN_VALUE;
0328: while (def != Byte.MAX_VALUE
0329: && labels.contains(Integer.toString(def)))
0330: ++def;
0331: ret = Integer.toString(def);
0332: } else if (utype.name().equals("short")) {
0333: short def = Short.MIN_VALUE;
0334: while (def != Short.MAX_VALUE
0335: && labels.contains(Integer.toString(def)))
0336: ++def;
0337: ret = Integer.toString(def);
0338: } else if (utype.name().equals("long")) {
0339: int def = Integer.MIN_VALUE;
0340: while (def != Integer.MAX_VALUE
0341: && labels.contains(Integer.toString(def)))
0342: ++def;
0343: ret = Integer.toString(def);
0344: } else if (utype.name().equals("long long")) {
0345: long def = Long.MIN_VALUE;
0346: while (def != Long.MAX_VALUE
0347: && labels.contains(Long.toString(def)))
0348: ++def;
0349: ret = Long.toString(def);
0350: } else if (utype.name().equals("unsigned short")) {
0351: short def = 0;
0352: while (def != Short.MAX_VALUE
0353: && labels.contains(Integer.toString(def)))
0354: ++def;
0355: ret = Integer.toString(def);
0356: } else if (utype.name().equals("unsigned long")) {
0357: int def = 0;
0358: while (def != Integer.MAX_VALUE
0359: && labels.contains(Integer.toString(def)))
0360: ++def;
0361: ret = Integer.toString(def);
0362: } else if (utype.name().equals("unsigned long long")) {
0363: long def = 0;
0364: while (def != Long.MAX_VALUE
0365: && labels.contains(Long.toString(def)))
0366: ++def;
0367: ret = Long.toString(def);
0368: }
0369:
0370: return ret;
0371: } // defaultDiscriminator
0372:
0373: /**
0374: *
0375: **/
0376: private Vector vectorizeLabels(Vector branchVector,
0377: boolean useIntsForEnums) {
0378: Vector mergedLabels = new Vector();
0379: Enumeration branches = branchVector.elements();
0380: while (branches.hasMoreElements()) {
0381: UnionBranch branch = (UnionBranch) branches.nextElement();
0382: Enumeration labels = branch.labels.elements();
0383: while (labels.hasMoreElements()) {
0384: Expression expr = (Expression) labels.nextElement();
0385: String str;
0386:
0387: if (unionIsEnum)
0388: if (useIntsForEnums)
0389: str = typePackage + "_"
0390: + Util.parseExpression(expr);
0391: else
0392: str = typePackage + Util.parseExpression(expr);
0393: else
0394: str = Util.parseExpression(expr);
0395:
0396: mergedLabels.addElement(str);
0397: }
0398: }
0399: return mergedLabels;
0400: } // vectorizeLabels
0401:
0402: /**
0403: *
0404: **/
0405: private String safeName(UnionEntry u, String name) {
0406: Enumeration e = u.branches().elements();
0407: while (e.hasMoreElements())
0408: if (((UnionBranch) e.nextElement()).typedef.name().equals(
0409: name)) {
0410: name = '_' + name;
0411: break;
0412: }
0413: return name;
0414: } // safeName
0415:
0416: /**
0417: *
0418: **/
0419: private boolean coversAll(UnionEntry u) {
0420: // This assumes that it is not possible to cover types other than
0421: // boolean and enums. This is not quite correct, but since octet
0422: // is not a valid discriminator type, it's not too bad in practice.
0423: // It may also be possible to cover a char type, but we won't worry
0424: // about that either.
0425: SymtabEntry utype = Util.typeOf(u.type());
0426:
0427: boolean coversAll = false;
0428: if (utype.name().equals("boolean")) {
0429: if (u.branches().size() == 2)
0430: coversAll = true;
0431: } else if (utype instanceof EnumEntry) {
0432: Vector labels = vectorizeLabels(u.branches(), true);
0433: if (labels.size() == ((EnumEntry) utype).elements().size())
0434: coversAll = true;
0435: }
0436:
0437: return coversAll;
0438: } // coversAll
0439:
0440: /**
0441: *
0442: **/
0443: private void writeBranchMethods(PrintWriter stream, UnionEntry u,
0444: UnionBranch branch, int i) {
0445: // Write getter
0446: stream.println();
0447: // <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
0448: //stream.println (" public " + Util.javaStatefulName (branch.typedef) + " " + branch.typedef.name () + " ()");
0449: stream.println(" public " + Util.javaName(branch.typedef)
0450: + " " + branch.typedef.name() + " ()");
0451: stream.println(" {");
0452: stream.println(" if (__uninitialized)");
0453: stream
0454: .println(" throw new org.omg.CORBA.BAD_OPERATION ();");
0455: stream.println(" verify" + branch.typedef.name()
0456: + " (__discriminator);");
0457: stream.println(" return ___" + branch.typedef.name() + ";");
0458: stream.println(" }");
0459:
0460: // Write setter(s)
0461: stream.println();
0462: // <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
0463: //stream.println (" public void " + branch.typedef.name () + " (" + Util.javaStatefulName (branch.typedef) + " value)");
0464: stream.println(" public void " + branch.typedef.name() + " ("
0465: + Util.javaName(branch.typedef) + " value)");
0466: stream.println(" {");
0467: if (branch.labels.size() == 0) {
0468: // This is a default branch
0469: stream.println(" __discriminator = "
0470: + defaultDiscriminator(u) + ";");
0471: } else {
0472: // This is a non-default branch
0473: if (unionIsEnum)
0474: stream
0475: .println(" __discriminator = "
0476: + typePackage
0477: + Util
0478: .parseExpression((Expression) branch.labels
0479: .firstElement()) + ";");
0480: else
0481: stream.println(" __discriminator = "
0482: + cast((Expression) branch.labels
0483: .firstElement(), u.type()) + ";");
0484: }
0485: stream.println(" ___" + branch.typedef.name() + " = value;");
0486: stream.println(" __uninitialized = false;");
0487: stream.println(" }");
0488:
0489: SymtabEntry utype = Util.typeOf(u.type());
0490:
0491: // If there are multiple labels for one branch, write the
0492: // setter that takes a discriminator.
0493: if (branch.labels.size() > 0 || branch.isDefault) {
0494: stream.println();
0495: // <f46082.51> Remove -stateful feature; javaStatefulName() obsolete.
0496: //stream.println (" public void " + branch.typedef.name () + " (" + Util.javaName (utype) + " discriminator, " + Util.javaStatefulName (branch.typedef) + " value)");
0497: stream.println(" public void " + branch.typedef.name()
0498: + " (" + Util.javaName(utype) + " discriminator, "
0499: + Util.javaName(branch.typedef) + " value)");
0500: stream.println(" {");
0501: stream.println(" verify" + branch.typedef.name()
0502: + " (discriminator);");
0503: stream.println(" __discriminator = discriminator;");
0504: stream.println(" ___" + branch.typedef.name()
0505: + " = value;");
0506: stream.println(" __uninitialized = false;");
0507: stream.println(" }");
0508: }
0509:
0510: // Write verifyXXX
0511: stream.println();
0512: stream.println(" private void verify" + branch.typedef.name()
0513: + " (" + Util.javaName(utype) + " discriminator)");
0514: stream.println(" {");
0515:
0516: boolean onlyOne = true;
0517:
0518: if (branch.isDefault && u.branches().size() == 1)
0519: ;// If all that is in this union is a default branch,
0520: // all discriminators are legal. Don't print any
0521: // body to this method in that case.
0522: else {
0523: // Otherwise this code is executed and a body is printed.
0524: stream.print(" if (");
0525: if (branch.isDefault) {
0526: Enumeration eBranches = u.branches().elements();
0527: while (eBranches.hasMoreElements()) {
0528: UnionBranch b = (UnionBranch) eBranches
0529: .nextElement();
0530: if (b != branch) {
0531: Enumeration eLabels = b.labels.elements();
0532: while (eLabels.hasMoreElements()) {
0533: Expression label = (Expression) eLabels
0534: .nextElement();
0535: if (!onlyOne)
0536: stream.print(" || ");
0537: if (unionIsEnum)
0538: stream.print("discriminator == "
0539: + typePackage
0540: + Util.parseExpression(label));
0541: else
0542: stream.print("discriminator == "
0543: + Util.parseExpression(label));
0544: onlyOne = false;
0545: }
0546: }
0547: }
0548: } else {
0549: Enumeration e = branch.labels.elements();
0550: while (e.hasMoreElements()) {
0551: Expression label = (Expression) e.nextElement();
0552: if (!onlyOne)
0553: stream.print(" && ");
0554: if (unionIsEnum)
0555: stream.print("discriminator != " + typePackage
0556: + Util.parseExpression(label));
0557: else
0558: stream.print("discriminator != "
0559: + Util.parseExpression(label));
0560: onlyOne = false;
0561: }
0562: }
0563: stream.println(")");
0564: stream
0565: .println(" throw new org.omg.CORBA.BAD_OPERATION ();");
0566: }
0567: stream.println(" }");
0568: } // writeBranchMethods
0569:
0570: ///////////////
0571: // From JavaGenerator
0572:
0573: /**
0574: *
0575: **/
0576:
0577: // Computes the total number of labels in the union, which is the sum
0578: // of the number of labels in each branch of the union. Note that the
0579: // label for the default branch has size 0, but still counts in the total
0580: // size.
0581: private int unionLabelSize(UnionEntry un) {
0582: int size = 0;
0583: Vector branches = un.branches();
0584: for (int i = 0; i < branches.size(); ++i) {
0585: UnionBranch branch = (UnionBranch) (branches.get(i));
0586: int branchSize = branch.labels.size();
0587: size += ((branchSize == 0) ? 1 : branchSize);
0588: }
0589: return size;
0590: }
0591:
0592: public int helperType(int index, String indent,
0593: TCOffsets tcoffsets, String name, SymtabEntry entry,
0594: PrintWriter stream) {
0595: TCOffsets innerOffsets = new TCOffsets();
0596: UnionEntry u = (UnionEntry) entry;
0597: String discTypeCode = "_disTypeCode" + index;
0598: String membersName = "_members" + index;
0599:
0600: // Build discriminator tc
0601: stream.println(indent + "org.omg.CORBA.TypeCode "
0602: + discTypeCode + ';');
0603: index = ((JavaGenerator) u.type().generator()).type(index + 1,
0604: indent, innerOffsets, discTypeCode, u.type(), stream);
0605: tcoffsets.bumpCurrentOffset(innerOffsets.currentOffset());
0606:
0607: stream.println(indent + "org.omg.CORBA.UnionMember[] "
0608: + membersName + " = new org.omg.CORBA.UnionMember ["
0609: + unionLabelSize(u) + "];");
0610: String tcOfMembers = "_tcOf" + membersName;
0611: String anyOfMembers = "_anyOf" + membersName;
0612: stream.println(indent + "org.omg.CORBA.TypeCode " + tcOfMembers
0613: + ';');
0614: stream.println(indent + "org.omg.CORBA.Any " + anyOfMembers
0615: + ';');
0616:
0617: innerOffsets = new TCOffsets();
0618: innerOffsets.set(entry);
0619: int offsetForUnion = innerOffsets.currentOffset();
0620: for (int i = 0; i < u.branches().size(); ++i) {
0621: UnionBranch branch = (UnionBranch) u.branches()
0622: .elementAt(i);
0623: TypedefEntry member = branch.typedef;
0624: Vector labels = branch.labels;
0625: String memberName = Util.stripLeadingUnderscores(member
0626: .name());
0627:
0628: if (labels.size() == 0) {
0629: stream.println();
0630: stream.println(indent + "// Branch for " + memberName
0631: + " (Default case)");
0632: SymtabEntry utype = Util.typeOf(u.type());
0633: stream
0634: .println(indent
0635: + anyOfMembers
0636: + " = org.omg.CORBA.ORB.init ().create_any ();");
0637: // For default member, label is the zero octet (per CORBA spec.)
0638: stream
0639: .println(indent
0640: + anyOfMembers
0641: + ".insert_octet ((byte)0); // default member label");
0642:
0643: // Build typecode
0644: innerOffsets.bumpCurrentOffset(4); // label value
0645: index = ((JavaGenerator) member.generator()).type(
0646: index, indent, innerOffsets, tcOfMembers,
0647: member, stream);
0648: int offsetSoFar = innerOffsets.currentOffset();
0649: innerOffsets = new TCOffsets();
0650: innerOffsets.set(entry);
0651: innerOffsets.bumpCurrentOffset(offsetSoFar
0652: - offsetForUnion);
0653:
0654: // Build union member
0655: stream.println(indent + membersName + '[' + i
0656: + "] = new org.omg.CORBA.UnionMember (");
0657: stream.println(indent + " \"" + memberName + "\",");
0658: stream.println(indent + " " + anyOfMembers + ',');
0659: stream.println(indent + " " + tcOfMembers + ',');
0660: stream.println(indent + " null);");
0661: } else {
0662: Enumeration enumeration = labels.elements();
0663: while (enumeration.hasMoreElements()) {
0664: Expression expr = (Expression) (enumeration
0665: .nextElement());
0666: String elem = Util.parseExpression(expr);
0667:
0668: stream.println();
0669: stream
0670: .println(indent + "// Branch for "
0671: + memberName + " (case label "
0672: + elem + ")");
0673:
0674: SymtabEntry utype = Util.typeOf(u.type());
0675:
0676: // Build any
0677: stream
0678: .println(indent
0679: + anyOfMembers
0680: + " = org.omg.CORBA.ORB.init ().create_any ();");
0681:
0682: if (utype instanceof PrimitiveEntry)
0683: stream.println(indent + anyOfMembers
0684: + ".insert_"
0685: + Util.collapseName(utype.name())
0686: + " ((" + Util.javaName(utype) + ')'
0687: + elem + ");");
0688: else { // it must be enum
0689: String enumClass = Util.javaName(utype);
0690: stream.println(indent
0691: + Util.helperName(utype, false)
0692: + ".insert (" + anyOfMembers + ", "
0693: + enumClass + '.' + elem + ");"); // <d61056>
0694: }
0695:
0696: // Build typecode
0697: innerOffsets.bumpCurrentOffset(4); // label value
0698: index = ((JavaGenerator) member.generator()).type(
0699: index, indent, innerOffsets, tcOfMembers,
0700: member, stream);
0701: int offsetSoFar = innerOffsets.currentOffset();
0702: innerOffsets = new TCOffsets();
0703: innerOffsets.set(entry);
0704: innerOffsets.bumpCurrentOffset(offsetSoFar
0705: - offsetForUnion);
0706:
0707: // Build union member
0708: stream.println(indent + membersName + '[' + i
0709: + "] = new org.omg.CORBA.UnionMember (");
0710: stream
0711: .println(indent + " \"" + memberName
0712: + "\",");
0713: stream.println(indent + " " + anyOfMembers + ',');
0714: stream.println(indent + " " + tcOfMembers + ',');
0715: stream.println(indent + " null);");
0716: }
0717: }
0718: }
0719:
0720: tcoffsets.bumpCurrentOffset(innerOffsets.currentOffset());
0721:
0722: // Build create_union_tc
0723: stream.println(indent + name
0724: + " = org.omg.CORBA.ORB.init ().create_union_tc ("
0725: + Util.helperName(u, true) + ".id (), \""
0726: + entry.name() + "\", " + discTypeCode + ", "
0727: + membersName + ");");
0728: return index;
0729: } // helperType
0730:
0731: public int type(int index, String indent, TCOffsets tcoffsets,
0732: String name, SymtabEntry entry, PrintWriter stream) {
0733: stream.println(indent + name + " = "
0734: + Util.helperName(entry, true) + ".type ();");
0735: return index;
0736: }
0737:
0738: public void helperRead(String entryName, SymtabEntry entry,
0739: PrintWriter stream) {
0740: stream.println(" " + entryName + " value = new " + entryName
0741: + " ();");
0742: read(0, " ", "value", entry, stream);
0743: stream.println(" return value;");
0744: }
0745:
0746: public void helperWrite(SymtabEntry entry, PrintWriter stream) {
0747: write(0, " ", "value", entry, stream);
0748: }
0749:
0750: public int read(int index, String indent, String name,
0751: SymtabEntry entry, PrintWriter stream) {
0752: UnionEntry u = (UnionEntry) entry;
0753: String disName = "_dis" + index++;
0754: SymtabEntry utype = Util.typeOf(u.type());
0755: Util.writeInitializer(indent, disName, "", utype, stream);
0756:
0757: if (utype instanceof PrimitiveEntry)
0758: index = ((JavaGenerator) utype.generator()).read(index,
0759: indent, disName, utype, stream);
0760: else
0761: stream
0762: .println(indent + disName + " = "
0763: + Util.helperName(utype, true)
0764: + ".read (istream);");
0765:
0766: if (utype.name().equals("boolean"))
0767: index = readBoolean(disName, index, indent, name, u, stream);
0768: else
0769: index = readNonBoolean(disName, index, indent, name, u,
0770: stream);
0771:
0772: return index;
0773: }
0774:
0775: private int readBoolean(String disName, int index, String indent,
0776: String name, UnionEntry u, PrintWriter stream) {
0777: UnionBranch firstBranch = (UnionBranch) u.branches()
0778: .firstElement();
0779: UnionBranch secondBranch;
0780:
0781: if (u.branches().size() == 2)
0782: secondBranch = (UnionBranch) u.branches().lastElement();
0783: else
0784: secondBranch = null;
0785:
0786: boolean firstBranchIsTrue = false;
0787: boolean noCases = false;
0788: try {
0789: if (u.branches().size() == 1
0790: && (u.defaultBranch() != null || firstBranch.labels
0791: .size() == 2)) {
0792: noCases = true;
0793: } else {
0794: Expression expr = (Expression) (firstBranch.labels
0795: .firstElement());
0796: Boolean bool = (Boolean) (expr.evaluate());
0797: firstBranchIsTrue = bool.booleanValue();
0798: }
0799: } catch (EvaluationException ex) {
0800: // no action
0801: }
0802:
0803: if (noCases) {
0804: // There is only a default label. Since there are no cases,
0805: // there is no need for if...else branches.
0806: index = readBranch(index, indent, firstBranch.typedef
0807: .name(), "", firstBranch.typedef, stream);
0808: } else {
0809: // If first branch is false, swap branches
0810: if (!firstBranchIsTrue) {
0811: UnionBranch tmp = firstBranch;
0812: firstBranch = secondBranch;
0813: secondBranch = tmp;
0814: }
0815:
0816: stream.println(indent + "if (" + disName + ')');
0817:
0818: if (firstBranch == null)
0819: stream
0820: .println(indent
0821: + " throw new org.omg.CORBA.BAD_OPERATION ();");
0822: else {
0823: stream.println(indent + '{');
0824: index = readBranch(index, indent + " ",
0825: firstBranch.typedef.name(), disName,
0826: firstBranch.typedef, stream);
0827: stream.println(indent + '}');
0828: }
0829:
0830: stream.println(indent + "else");
0831:
0832: if (secondBranch == null)
0833: stream
0834: .println(indent
0835: + " throw new org.omg.CORBA.BAD_OPERATION ();");
0836: else {
0837: stream.println(indent + '{');
0838: index = readBranch(index, indent + " ",
0839: secondBranch.typedef.name(), disName,
0840: secondBranch.typedef, stream);
0841: stream.println(indent + '}');
0842: }
0843: }
0844:
0845: return index;
0846: }
0847:
0848: private int readNonBoolean(String disName, int index,
0849: String indent, String name, UnionEntry u, PrintWriter stream) {
0850: SymtabEntry utype = Util.typeOf(u.type());
0851:
0852: if (utype instanceof EnumEntry)
0853: stream
0854: .println(indent + "switch (" + disName
0855: + ".value ())");
0856: else
0857: stream.println(indent + "switch (" + disName + ')');
0858:
0859: stream.println(indent + '{');
0860: String typePackage = Util.javaQualifiedName(utype) + '.';
0861:
0862: Enumeration e = u.branches().elements();
0863: while (e.hasMoreElements()) {
0864: UnionBranch branch = (UnionBranch) e.nextElement();
0865: Enumeration labels = branch.labels.elements();
0866:
0867: while (labels.hasMoreElements()) {
0868: Expression label = (Expression) labels.nextElement();
0869:
0870: if (utype instanceof EnumEntry) {
0871: String key = Util.parseExpression(label);
0872: stream.println(indent + " case " + typePackage
0873: + '_' + key + ':');
0874: } else
0875: stream.println(indent + " case "
0876: + cast(label, utype) + ':');
0877: }
0878:
0879: if (!branch.typedef.equals(u.defaultBranch())) {
0880: index = readBranch(index, indent + " ",
0881: branch.typedef.name(),
0882: branch.labels.size() > 1 ? disName : "",
0883: branch.typedef, stream);
0884: stream.println(indent + " break;");
0885: }
0886: }
0887:
0888: // We need a default branch unless all of the case of the discriminator type
0889: // are listed in the case branches.
0890: if (!coversAll(u)) {
0891: stream.println(indent + " default:");
0892:
0893: if (u.defaultBranch() == null) {
0894: // If the union does not have a default branch, we still need to initialize
0895: // the discriminator.
0896: stream.println(indent + " value._default( "
0897: + disName + " ) ;");
0898: } else {
0899: index = readBranch(index, indent + " ", u
0900: .defaultBranch().name(), disName, u
0901: .defaultBranch(), stream);
0902: }
0903:
0904: stream.println(indent + " break;");
0905: }
0906:
0907: stream.println(indent + '}');
0908:
0909: return index;
0910: }
0911:
0912: private int readBranch(int index, String indent, String name,
0913: String disName, TypedefEntry entry, PrintWriter stream) {
0914: SymtabEntry type = entry.type();
0915: Util.writeInitializer(indent, '_' + name, "", entry, stream);
0916:
0917: if (!entry.arrayInfo().isEmpty()
0918: || type instanceof SequenceEntry
0919: || type instanceof PrimitiveEntry
0920: || type instanceof StringEntry) {
0921: index = ((JavaGenerator) entry.generator()).read(index,
0922: indent, '_' + name, entry, stream);
0923: } else {
0924: stream.println(indent + '_' + name + " = "
0925: + Util.helperName(type, true) + ".read (istream);");
0926: }
0927:
0928: stream.print(indent + "value." + name + " (");
0929: if (disName == "")
0930: stream.println("_" + name + ");");
0931: else
0932: stream.println(disName + ", " + "_" + name + ");");
0933:
0934: return index;
0935: }
0936:
0937: /**
0938: *
0939: **/
0940: public int write(int index, String indent, String name,
0941: SymtabEntry entry, PrintWriter stream) {
0942: UnionEntry u = (UnionEntry) entry;
0943: SymtabEntry utype = Util.typeOf(u.type());
0944: if (utype instanceof PrimitiveEntry)
0945: index = ((JavaGenerator) utype.generator()).write(index,
0946: indent, name + ".discriminator ()", utype, stream);
0947: else
0948: stream.println(indent + Util.helperName(utype, true)
0949: + ".write (ostream, " + name
0950: + ".discriminator ());"); // <d61056>
0951: if (utype.name().equals("boolean"))
0952: index = writeBoolean(name + ".discriminator ()", index,
0953: indent, name, u, stream);
0954: else
0955: index = writeNonBoolean(name + ".discriminator ()", index,
0956: indent, name, u, stream);
0957: return index;
0958: } // write
0959:
0960: /**
0961: *
0962: **/
0963: private int writeBoolean(String disName, int index, String indent,
0964: String name, UnionEntry u, PrintWriter stream) {
0965: SymtabEntry utype = Util.typeOf(u.type());
0966: UnionBranch firstBranch = (UnionBranch) u.branches()
0967: .firstElement();
0968: UnionBranch secondBranch;
0969: if (u.branches().size() == 2)
0970: secondBranch = (UnionBranch) u.branches().lastElement();
0971: else
0972: secondBranch = null;
0973: boolean firstBranchIsTrue = false;
0974: boolean noCases = false;
0975: try {
0976: if (u.branches().size() == 1
0977: && (u.defaultBranch() != null || firstBranch.labels
0978: .size() == 2))
0979: noCases = true;
0980: else
0981: firstBranchIsTrue = ((Boolean) ((Expression) firstBranch.labels
0982: .firstElement()).evaluate()).booleanValue();
0983: } catch (EvaluationException ex) {
0984: }
0985:
0986: if (noCases) {
0987: // There is only a default label. Since there are no cases,
0988: // there is no need for if...else branches.
0989: index = writeBranch(index, indent, name,
0990: firstBranch.typedef, stream);
0991: } else {
0992: // If first branch is false, swap branches
0993: if (!firstBranchIsTrue) {
0994: UnionBranch tmp = firstBranch;
0995: firstBranch = secondBranch;
0996: secondBranch = tmp;
0997: }
0998: stream.println(indent + "if (" + disName + ')');
0999: if (firstBranch == null)
1000: stream
1001: .println(indent
1002: + " throw new org.omg.CORBA.BAD_OPERATION ();");
1003: else {
1004: stream.println(indent + '{');
1005: index = writeBranch(index, indent + " ", name,
1006: firstBranch.typedef, stream);
1007: stream.println(indent + '}');
1008: }
1009: stream.println(indent + "else");
1010: if (secondBranch == null)
1011: stream
1012: .println(indent
1013: + " throw new org.omg.CORBA.BAD_OPERATION ();");
1014: else {
1015: stream.println(indent + '{');
1016: index = writeBranch(index, indent + " ", name,
1017: secondBranch.typedef, stream);
1018: stream.println(indent + '}');
1019: }
1020: }
1021: return index;
1022: } // writeBoolean
1023:
1024: /**
1025: *
1026: **/
1027: private int writeNonBoolean(String disName, int index,
1028: String indent, String name, UnionEntry u, PrintWriter stream) {
1029: SymtabEntry utype = Util.typeOf(u.type());
1030: if (utype instanceof EnumEntry)
1031: stream.println(indent + "switch (" + name
1032: + ".discriminator ().value ())");
1033: else
1034: stream.println(indent + "switch (" + name
1035: + ".discriminator ())");
1036: stream.println(indent + "{");
1037: String typePackage = Util.javaQualifiedName(utype) + '.';
1038: Enumeration e = u.branches().elements();
1039: while (e.hasMoreElements()) {
1040: UnionBranch branch = (UnionBranch) e.nextElement();
1041: Enumeration labels = branch.labels.elements();
1042: while (labels.hasMoreElements()) {
1043: Expression label = (Expression) labels.nextElement();
1044: if (utype instanceof EnumEntry) {
1045: String key = Util.parseExpression(label);
1046: stream.println(indent + " case " + typePackage
1047: + '_' + key + ":");
1048: } else
1049: stream.println(indent + " case "
1050: + cast(label, utype) + ':');
1051: }
1052: if (!branch.typedef.equals(u.defaultBranch())) {
1053: index = writeBranch(index, indent + " ", name,
1054: branch.typedef, stream);
1055: stream.println(indent + " break;");
1056: }
1057: }
1058: if (u.defaultBranch() != null) {
1059: stream.println(indent + " default:");
1060: index = writeBranch(index, indent + " ", name, u
1061: .defaultBranch(), stream);
1062: stream.println(indent + " break;");
1063: }
1064: stream.println(indent + "}");
1065: return index;
1066: } // writeNonBoolean
1067:
1068: /**
1069: *
1070: **/
1071: private int writeBranch(int index, String indent, String name,
1072: TypedefEntry entry, PrintWriter stream) {
1073: SymtabEntry type = entry.type();
1074: if (!entry.arrayInfo().isEmpty()
1075: || type instanceof SequenceEntry
1076: || type instanceof PrimitiveEntry
1077: || type instanceof StringEntry)
1078: index = ((JavaGenerator) entry.generator()).write(index,
1079: indent, name + '.' + entry.name() + " ()", entry,
1080: stream);
1081: else
1082: stream.println(indent + Util.helperName(type, true)
1083: + ".write (ostream, " + name + '.' + entry.name()
1084: + " ());"); // <d61056>
1085: return index;
1086: } // writeBranch
1087:
1088: // From JavaGenerator
1089: ///////////////
1090:
1091: /**
1092: *
1093: **/
1094: private String cast(Expression expr, SymtabEntry type) {
1095: String ret = Util.parseExpression(expr);
1096: if (type.name().indexOf("short") >= 0) {
1097: if (expr.value() instanceof Long) {
1098: long value = ((Long) expr.value()).longValue();
1099: if (value > Short.MAX_VALUE)
1100: ret = "(short)(" + ret + ')';
1101: } else if (expr.value() instanceof Integer) {
1102: int value = ((Integer) expr.value()).intValue();
1103: if (value > Short.MAX_VALUE)
1104: ret = "(short)(" + ret + ')';
1105: }
1106: } else if (type.name().indexOf("long") >= 0) {
1107: if (expr.value() instanceof Long) {
1108: long value = ((Long) expr.value()).longValue();
1109: // value == Integer.MIN_VALUE because if the number is
1110: // Integer.MIN_VALUE, then it will have the 'L' suffix and
1111: // the cast will be necessary.
1112: if (value > Integer.MAX_VALUE
1113: || value == Integer.MIN_VALUE)
1114: ret = "(int)(" + ret + ')';
1115: } else if (expr.value() instanceof Integer) {
1116: int value = ((Integer) expr.value()).intValue();
1117: // value == Integer.MIN_VALUE because if the number is
1118: // Integer.MIN_VALUE, then it will have the 'L' suffix and
1119: // the cast will be necessary.
1120: if (value > Integer.MAX_VALUE
1121: || value == Integer.MIN_VALUE)
1122: ret = "(int)(" + ret + ')';
1123: }
1124: }
1125: return ret;
1126: } // cast
1127:
1128: protected Hashtable symbolTable = null;
1129: protected UnionEntry u = null;
1130: protected PrintWriter stream = null;
1131: protected SymtabEntry utype = null;
1132: protected boolean unionIsEnum;
1133: protected String typePackage = "";
1134: } // class UnionGen
|