ValueGen.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25/*
26 * COMPONENT_NAME: idl.toJava
27 *
28 * ORIGINS: 27
29 *
30 * Licensed Materials - Property of IBM
31 * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
32 * RMI-IIOP v1.0
33 *
34 */
35
36package com.sun.tools.corba.se.idl.toJavaPortable;
37
38// NOTES:
39// -F46082.51<daz> Remove -stateful feature; javaStatefulName() obsolete.
40// -D57067 <klr> suppress default init if an emit init explicitly specified.
41// -D59071 <daz> Clone method entries when their content needs modification.
42// -D59092 <klr> Valuetype supporting interfaces should implement interface.
43// -D59418 <klr> Custom values implement org.omg.CORBA.CustomMarshal
44// -D59418 <klr> Invert read/read_Value, write/write_Value for Simon
45// -D60929 <klr> Update for RTF2.4 changes
46// -D62018 <klr> write_value for value with value field x calls xHelper.write.
47// -D62062 <klr> Add _write to value Helper to marshal state.
48//   write_value for value subclass calls parent._write
49// -D61650<daz> Remove '\n' from generated strings; use println()'s.
50
51import java.io.File;
52import java.io.PrintWriter;
53import java.util.Hashtable;
54import java.util.Enumeration;
55import java.util.Vector;
56
57import com.sun.tools.corba.se.idl.GenFileStream;
58import com.sun.tools.corba.se.idl.InterfaceEntry;
59import com.sun.tools.corba.se.idl.SymtabEntry;
60import com.sun.tools.corba.se.idl.TypedefEntry;
61import com.sun.tools.corba.se.idl.ValueEntry;
62import com.sun.tools.corba.se.idl.ValueBoxEntry;
63import com.sun.tools.corba.se.idl.InterfaceState;
64import com.sun.tools.corba.se.idl.MethodEntry;
65import com.sun.tools.corba.se.idl.PrimitiveEntry;
66import com.sun.tools.corba.se.idl.SequenceEntry;
67import com.sun.tools.corba.se.idl.StringEntry;
68import com.sun.tools.corba.se.idl.StructEntry;
69
70/**
71 *
72 **/
73public class ValueGen implements com.sun.tools.corba.se.idl.ValueGen, JavaGenerator
74{
75  /**
76   * Public zero-argument constructor.
77   **/
78  public ValueGen ()
79  {
80  } // ctor
81
82  /**
83   *
84   **/
85  public void generate (Hashtable symbolTable, ValueEntry v, PrintWriter str)
86  {
87    this.symbolTable = symbolTable;
88    this.v = v;
89    init ();
90
91    openStream ();
92    if (stream == null)
93      return;
94    generateTie ();
95    generateHelper ();
96    generateHolder ();
97    writeHeading ();
98    writeBody ();
99    writeClosing ();
100    closeStream ();
101  } // generate
102
103  /**
104   * Initialize members unique to this generator.
105   **/
106  protected void init ()
107  {
108    emit = ((Arguments)Compile.compiler.arguments).emit;
109    factories = (Factories)Compile.compiler.factories ();
110  } // init
111
112  /**
113   *
114   **/
115  protected void openStream ()
116  {
117    stream = Util.stream (v, ".java");
118  } // openStream
119
120  /**
121   * Generate a Tie class only when the user specifies the TIE option
122   * and the valuetype does support an interface.
123   **/
124  protected void generateTie ()
125  {
126    boolean tie = ((Arguments)Compile.compiler.arguments).TIEServer;
127    if (v.supports ().size () > 0  && tie)
128    {
129      Factories factories = (Factories)Compile.compiler.factories ();
130      factories.skeleton ().generate (symbolTable, v);
131    }
132  } // generateTie
133
134  /**
135   *
136   **/
137  protected void generateHelper ()
138  {
139    ((Factories)Compile.compiler.factories ()).helper ().generate (symbolTable, v);
140  } // generateHelper
141
142  /**
143   *
144   **/
145  protected void generateHolder ()
146  {
147    ((Factories)Compile.compiler.factories ()).holder ().generate (symbolTable, v);
148  } // generateHolder
149
150  /**
151   *
152   **/
153  protected void writeHeading ()
154  {
155    Util.writePackage (stream, v);
156    Util.writeProlog (stream, ((GenFileStream)stream).name ());
157
158    if (v.comment () != null)
159      v.comment ().generate ("", stream);
160
161    if (v.isAbstract ())
162    {
163      writeAbstract ();
164      return;
165    }
166    else
167      stream.print ("public class " + v.name ());
168
169    // There should always be at least one parent: ValueBase
170    SymtabEntry parent = (SymtabEntry) v.derivedFrom ().elementAt (0);
171
172    // If parent is ValueBase, it's mapped to java.io.Serializable
173    String parentName = Util.javaName (parent);
174    boolean impl = false;
175
176    if (parentName.equals ("java.io.Serializable"))
177    {
178//    stream.print (" implements org.omg.CORBA.portable.ValueBase, org.omg.CORBA.portable.Streamable");
179      stream.print (" implements org.omg.CORBA.portable.ValueBase"); // <d60929>
180      impl = true;
181    }
182    else if ( !((ValueEntry)parent).isAbstract ())
183      stream.print (" extends " + parentName);
184
185    // if inheriting from abstract values
186    for (int i = 0; i < v.derivedFrom ().size (); i++) {
187      parent = (SymtabEntry) v.derivedFrom ().elementAt (i);
188      if ( ((ValueEntry)parent).isAbstract ())
189      {
190        if (!impl)
191        {
192          stream.print (" implements ");
193          impl = true;
194        }
195        else
196          stream.print (", ");
197        stream.print (Util.javaName (parent));
198      }
199    }
200// <d59092-klr> Valuetype supporting interface implement Operations interface
201// for supported IDL interface
202    if (((ValueEntry)v).supports ().size () > 0) {
203      if (!impl)
204      {
205        stream.print (" implements ");
206        impl = true;
207      }
208      else
209        stream.print (", ");
210
211      InterfaceEntry s =(InterfaceEntry)((ValueEntry)v).supports().elementAt(0);
212      // abstract supported classes don't have "Operations"
213      if (s.isAbstract ())
214         stream.print (Util.javaName (s));
215      else
216          stream.print (Util.javaName (s) + "Operations");
217      }
218
219//  <d59418> Custom valuetypes implement org.omg.CORBA.CustomMarshal.
220    if ( ((ValueEntry)v).isCustom ()) {
221      if (!impl)
222      {
223        stream.print (" implements ");
224        impl = true;
225      }
226      else
227        stream.print (", ");
228
229      stream.print ("org.omg.CORBA.CustomMarshal ");
230      }
231
232    stream.println ();
233    stream.println ("{");
234  } // writeHeading
235
236  /**
237   *
238   **/
239  protected void writeBody ()
240  {
241    writeMembers ();
242    writeInitializers ();
243    writeConstructor (); // <d57067>
244    writeTruncatable (); // <d60929>
245    writeMethods ();
246  } // writeBody
247
248  /**
249   *
250   **/
251  protected void writeClosing ()
252  {
253   if (v.isAbstract ())
254     stream.println ("} // interface " + v.name ());
255   else
256     stream.println ("} // class " + v.name ());
257  } // writeClosing
258
259  /**
260   *
261   **/
262  protected void closeStream ()
263  {
264    stream.close ();
265  } // closeStream
266
267  /**
268   *
269   **/
270  protected void writeConstructor ()
271  {
272   // Per Simon, 9/3/98, emit a protected default constructor
273   if (!v.isAbstract () && !explicitDefaultInit) { // <d57067 - klr>
274        stream.println ("  protected " + v.name () + " () {}");
275        stream.println ();
276    }
277  } // writeConstructor
278
279  /**
280   *
281   **/
282  protected void writeTruncatable () // <d60929>
283  {
284   // Per Simon, 4/6/98, emit _truncatable_ids()
285   if (!v.isAbstract ()) {
286        stream.println ("  public String[] _truncatable_ids() {");
287        stream.println ("      return " + Util.helperName(v, true) + ".get_instance().get_truncatable_base_ids();"); // <d61056>
288        stream.println ("  }");
289        stream.println ();
290    }
291  } // writeTruncatable
292
293  /**
294   *
295   **/
296  protected void writeMembers ()
297  {
298    // if the value type contains no data members, a null return is expected
299    if (v.state () == null)
300      return;
301
302    for (int i = 0; i < v.state ().size (); i ++)
303    {
304      InterfaceState member = (InterfaceState) v.state ().elementAt (i);
305      SymtabEntry entry = (SymtabEntry) member.entry;
306      Util.fillInfo (entry);
307
308      if (entry.comment () != null)
309        entry.comment ().generate (" ", stream);
310
311      String modifier = "  ";
312      if (member.modifier == InterfaceState.Public)
313        modifier = "  public ";
314      Util.writeInitializer (modifier, entry.name (), "", entry, stream);
315    }
316  } // writeMembers
317
318  /**
319   *
320   **/
321  protected void writeInitializers ()
322  {
323    Vector init = v.initializers ();
324    if (init != null)
325    {
326      stream.println ();
327      for (int i = 0; i < init.size (); i++)
328      {
329        MethodEntry element = (MethodEntry) init.elementAt (i);
330        element.valueMethod (true);
331        ((MethodGen) element.generator ()). interfaceMethod (symbolTable, element, stream);
332        if (element.parameters ().isEmpty ()) // <d57067-klr>
333          explicitDefaultInit = true;
334      }
335    }
336  } // writeInitializers
337
338  /**
339   *
340   **/
341  protected void writeMethods ()
342  {
343    // contained vector contains methods, attributes, const, enums, exceptions,
344    // structs, unions, or typedefs that are declared inside the value object.
345    // State members of the nested types are also included in this vector.
346    // Thus, if the declaration of a constructed type is nested in the decl.
347    // of a state member, e.g   struct x {boolean b;}  memberx;
348    // the generation of the nested type must be handled here.
349    Enumeration e = v.contained ().elements ();
350    while (e.hasMoreElements ())
351    {
352      SymtabEntry contained = (SymtabEntry)e.nextElement ();
353      if (contained instanceof MethodEntry)
354      {
355        MethodEntry element = (MethodEntry)contained;
356        ((MethodGen)element.generator ()).interfaceMethod (symbolTable, element, stream);
357      }
358      else
359      {
360        // Generate the type referenced by the typedef.
361        if (contained instanceof TypedefEntry)
362          contained.type ().generate (symbolTable, stream);
363
364        // Note that we also need to generate the typedef itself if
365        // contained is a typedef.
366        contained.generate (symbolTable, stream);
367      }
368    }
369
370    // Abstract values are mapped to interfaces. There is no need to generate
371    // the bindings for inheriting methods in case of inheritance from other
372    // abstract values or supporting interface
373    if (v.isAbstract ())
374        return;
375
376    // workaround: if the value type doesnot support any interfaces, a null
377    // return is expected instead of an empty vector
378
379    // if supporting an interfaces, generate bindings for inheriting methods
380    if (v.supports ().size () > 0)
381    {
382      InterfaceEntry intf = (InterfaceEntry) v.supports ().elementAt (0);
383      Enumeration el = intf.allMethods ().elements ();
384      while (el.hasMoreElements ())
385      {
386        MethodEntry m = (MethodEntry) el.nextElement ();
387        // <d59071> Don't alter the symbol table/emit list elements!
388        //m.container (v);
389        //((MethodGen)m.generator ()).interfaceMethod (symbolTable, m, stream);
390        MethodEntry mClone = (MethodEntry)m.clone ();
391        mClone.container (v);
392        ((MethodGen)mClone.generator ()).interfaceMethod (symbolTable, mClone, stream);
393      }
394    }
395
396    // if inheriting from abstract values, generating bindings for all
397    // inheriting methods
398    for (int i = 0; i < v.derivedFrom ().size (); i++) {
399      ValueEntry parentValue = (ValueEntry) v.derivedFrom ().elementAt (i);
400      if (parentValue.isAbstract ())
401      {
402        Enumeration el = parentValue.allMethods ().elements ();
403        while (el.hasMoreElements ())
404        {
405           MethodEntry m = (MethodEntry) el.nextElement ();
406          // <d59071> Don't alter the symbol table/emit list elements!
407          //m.container (v);
408          //((MethodGen)m.generator ()).interfaceMethod (symbolTable, m, stream);
409          MethodEntry mClone = (MethodEntry)m.clone ();
410          mClone.container (v);
411          ((MethodGen)mClone.generator ()).interfaceMethod (symbolTable, mClone, stream);
412        }
413      }
414    }
415
416  //writeStreamableMethods ();
417  } // writeMethods
418
419  /**
420   *
421   **/
422  protected void writeStreamableMethods ()
423  {
424    stream.println ("  public void _read (org.omg.CORBA.portable.InputStream istream)");
425    stream.println ("  {");
426    read (0, "    ", "this", v, stream);
427    stream.println ("  }");
428    stream.println ();
429    stream.println ("  public void _write (org.omg.CORBA.portable.OutputStream ostream)");
430    stream.println ("  {");
431    write (0, "    ", "this", v, stream);
432    stream.println ("  }");
433    stream.println ();
434    stream.println ("  public org.omg.CORBA.TypeCode _type ()");
435    stream.println ("  {");
436    stream.println ("    return " + Util.helperName (v, false) + ".type ();"); // <d61056>
437    stream.println ("  }");
438  } // writeStreamableMethods
439
440  ///////////////
441  // From JavaGenerator
442
443  public int helperType (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)
444  {
445    ValueEntry vt = (ValueEntry) entry;
446    Vector state = vt.state ();
447    int noOfMembers = state == null ? 0 : state.size ();
448    String members = "_members" + index++;
449    String tcOfMembers = "_tcOf" + members;
450
451    stream.println (indent + "org.omg.CORBA.ValueMember[] "
452                    + members + " = new org.omg.CORBA.ValueMember["
453                    + noOfMembers
454                    + "];");
455    stream.println (indent + "org.omg.CORBA.TypeCode " + tcOfMembers + " = null;");
456    //stream.println (""); // <d61650>
457
458    String definedInrepId = "_id";
459    String repId, version;
460
461    for (int k=0; k<noOfMembers; k++)
462    {
463      InterfaceState valueMember = (InterfaceState)state.elementAt (k);
464      TypedefEntry member = (TypedefEntry)valueMember.entry;
465      SymtabEntry mType = Util.typeOf (member);
466      if (hasRepId (member))
467      {
468        repId = Util.helperName (mType, true) + ".id ()"; // <d61056>
469        if (mType instanceof ValueEntry || mType instanceof ValueBoxEntry)
470          // OBV spec is silent on defining VersionSpec for valuetype RepIds
471          version = "\"\"";
472        else
473        {
474          String id = mType.repositoryID ().ID ();
475          version = '"' + id.substring (id.lastIndexOf (':')+1) + '"';
476        }
477      }
478      else
479      {
480        repId = "\"\"";
481        version = "\"\"";
482      }
483
484      // Get TypeCode for valuetype member and store it var. name given by tcOfMembers
485      stream.println (indent + "// ValueMember instance for " + member.name ());
486      index = ((JavaGenerator)member.generator ()).type (index, indent, tcoffsets, tcOfMembers, member, stream);
487      stream.println (indent + members + "[" + k + "] = new org.omg.CORBA.ValueMember ("  // <d61650>
488          + '"' + member.name () + "\", ");                               // name
489      stream.println (indent + "    " + repId + ", ");                    // id
490      stream.println (indent + "    " + definedInrepId + ", ");           // defined_in
491      stream.println (indent + "    " + version + ", ");                  // version
492      stream.println (indent + "    " + tcOfMembers + ", ");              // type
493      stream.println (indent + "    " + "null, ");                        // type_def
494      stream.println (indent + "    " + "org.omg.CORBA." +
495          (valueMember.modifier == InterfaceState.Public ?
496              "PUBLIC_MEMBER" : "PRIVATE_MEMBER") + ".value" + ");");     // access
497    } // end for
498
499    stream.println (indent + name + " = org.omg.CORBA.ORB.init ().create_value_tc ("
500                    + "_id, "
501                    + '"' + entry.name () + "\", "
502                    + getValueModifier (vt) + ", "
503                    + getConcreteBaseTypeCode (vt) + ", "
504                    + members
505                    + ");");
506
507    return index;
508  } // helperType
509
510  public int type (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream) {
511    stream.println (indent + name + " = " + Util.helperName (entry, true) + ".type ();"); // <d61056>
512    return index;
513  } // type
514
515  // Check for types which don't have a Repository ID: primitive,
516  // string, arrays and sequences.
517
518  private static boolean hasRepId (SymtabEntry member)
519  {
520    SymtabEntry mType = Util.typeOf (member);
521    return !( mType instanceof PrimitiveEntry ||
522              mType instanceof StringEntry ||
523              ( mType instanceof TypedefEntry &&
524                !(((TypedefEntry)mType).arrayInfo ().isEmpty ()) ) ||
525              ( mType instanceof TypedefEntry && member.type () instanceof SequenceEntry) );
526  } // hasRepId
527
528  private static String getValueModifier (ValueEntry vt)
529  {
530    String mod = "NONE";
531    if (vt.isCustom ())
532      mod = "CUSTOM";
533    else if (vt.isAbstract ())
534      mod = "ABSTRACT";
535    else if (vt.isSafe ())
536      mod = "TRUNCATABLE";
537    return "org.omg.CORBA.VM_" + mod + ".value";
538  } // getValueModifier
539
540  private static String getConcreteBaseTypeCode (ValueEntry vt)
541  {
542    Vector v = vt.derivedFrom ();
543    if (!vt.isAbstract ())
544    {
545      SymtabEntry base = (SymtabEntry)vt.derivedFrom ().elementAt (0);
546      if (!"ValueBase".equals (base.name ()))
547        return Util.helperName (base, true) + ".type ()"; // <d61056>
548    }
549    return "null";
550  } // getConcreteBaseTypeCode
551
552  public void helperRead (String entryName, SymtabEntry entry, PrintWriter stream)
553  {
554  // <d59418 - KLR> per Simon, make "static" read call istream.read_value.
555  //                put real marshalling code in read_value.
556
557    if (((ValueEntry)entry).isAbstract ())
558    {
559      stream.println ("    throw new org.omg.CORBA.BAD_OPERATION (\"abstract value cannot be instantiated\");");
560    }
561    else
562    {
563    stream.println ("    return (" + entryName +") ((org.omg.CORBA_2_3.portable.InputStream) istream).read_value (get_instance());"); // <d60929>
564    }
565    stream.println ("  }");
566    stream.println ();
567
568    // done with "read", now do "read_value with real marshalling code.
569
570    stream.println ("  public java.io.Serializable read_value (org.omg.CORBA.portable.InputStream istream)"); // <d60929>
571    stream.println ("  {");
572
573    // per Simon, 3/3/99, read_value for custom values throws an exception
574    if (((ValueEntry)entry).isAbstract ())
575    {
576      stream.println ("    throw new org.omg.CORBA.BAD_OPERATION (\"abstract value cannot be instantiated\");");
577    }
578    else
579      if (((ValueEntry)entry).isCustom ())
580      {
581        stream.println ("    throw new org.omg.CORBA.BAD_OPERATION (\"custom values should use unmarshal()\");");
582      }
583      else
584      {
585        stream.println ("    " + entryName + " value = new " + entryName + " ();");
586        read (0, "    ", "value", entry, stream);
587        stream.println ("    return value;");
588      }
589    stream.println ("  }");
590    stream.println ();
591    // End of normal read method
592
593    // Per Simon, 8/26/98 - Value helpers get an additional overloaded
594    // read method where the value is passed in instead of "new'd" up. This is
595    // used for reading parent value state.
596
597    // Per Simon, 3/3/99 - Don't change this "read" for custom marshalling
598    stream.println ("  public static void read (org.omg.CORBA.portable.InputStream istream, " + entryName + " value)");
599    stream.println ("  {");
600    read (0, "    ", "value", entry, stream);
601  } // helperRead
602
603  public int read (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
604  {
605    // First do the state members from concrete parent hierarchy
606    Vector vParents = ((ValueEntry) entry).derivedFrom ();
607    if (vParents != null && vParents.size() != 0)
608    {
609      ValueEntry parent = (ValueEntry) vParents.elementAt (0);
610      if (parent == null)
611        return index;
612      // Per Simon, 4/6/99 - call parent read. <d60929>
613      if (! Util.javaQualifiedName(parent).equals ("java.io.Serializable")) // <d60929>
614          stream.println(indent + Util.helperName (parent, true) + ".read (istream, value);"); // <d60929> // <d61056>
615    }
616
617    Vector vMembers = ((ValueEntry) entry).state ();
618    int noOfMembers = vMembers == null ? 0 : vMembers.size ();
619
620    for (int k = 0; k < noOfMembers; k++)
621    {
622      TypedefEntry member = (TypedefEntry)((InterfaceState)vMembers.elementAt (k)).entry;
623      String memberName = member.name ();
624      SymtabEntry mType = member.type ();
625
626      if (mType instanceof PrimitiveEntry ||
627          mType instanceof TypedefEntry   ||
628          mType instanceof SequenceEntry  ||
629          mType instanceof StringEntry    ||
630          !member.arrayInfo ().isEmpty ())
631        index = ((JavaGenerator)member.generator ()).read (index, indent, name + '.' + memberName, member, stream);
632      else if (mType instanceof ValueEntry)
633      {
634        String returnType = Util.javaQualifiedName (mType);
635        if (mType instanceof ValueBoxEntry)
636          // <f46082.51> Remove -stateful.
637          //returnType = Util.javaStatefulName (mType);
638          returnType = Util.javaName (mType);
639        stream.println ("    " + name + '.' + memberName + " = (" + returnType +
640                        ") ((org.omg.CORBA_2_3.portable.InputStream)istream).read_value (" + Util.helperName (mType, true) +  // <d61056>
641                        ".get_instance ());"); // <d61056>
642      }
643      else
644        stream.println (indent + name + '.' + memberName + " = " +
645                        Util.helperName (mType, true) + ".read (istream);"); // <d61056>
646    }
647
648    return index;
649  } // read
650
651  public void helperWrite (SymtabEntry entry, PrintWriter stream)
652  {
653    // <d59418 - KLR> per Simon, make "static" write call istream.write_value.
654    //              put real marshalling code in write_value.
655    stream.println ("    ((org.omg.CORBA_2_3.portable.OutputStream) ostream).write_value (value, get_instance());"); // <d60929>
656    stream.println ("  }");
657    stream.println ();
658
659    // <d62062>
660    // per Simon, 4/27/99, add static _write that marshals the state of this
661    //  value for non-custom valuetypes
662    if (!((ValueEntry)entry).isCustom ())
663    {
664       stream.println ("  public static void _write (org.omg.CORBA.portable.OutputStream ostream, " + Util.javaName (entry) + " value)");
665       stream.println ("  {");
666       write (0, "    ", "value", entry, stream);
667       stream.println ("  }");
668       stream.println ();
669    }
670
671    // done with "_write", now do "write_value
672    stream.println ("  public void write_value (org.omg.CORBA.portable.OutputStream ostream, java.io.Serializable obj)"); // <d60929>
673    stream.println ("  {");
674
675    // per Simon, 3/3/99, write_value for custom values throws an exception
676    if (((ValueEntry)entry).isCustom ())
677    {
678      stream.println ("    throw new org.omg.CORBA.BAD_OPERATION (\"custom values should use marshal()\");");
679    }
680    else {
681      String entryName = Util.javaName(entry);
682      stream.println ("    _write (ostream, (" + entryName + ") obj);"); // <d62062>
683//      write (0, "    ", "value", entry, stream); <d62062>
684    }
685  } // helperWrite
686
687  public int write (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
688  {
689    // First do the state members from concrete parent hierarchy
690    Vector vParents = ((ValueEntry)entry).derivedFrom ();
691    if (vParents != null && vParents.size () != 0)
692    {
693      ValueEntry parent = (ValueEntry)vParents.elementAt (0);
694      if (parent == null)
695        return index;
696      // Per Simon, 4/06/99 - call parent write. <d60929>
697      // Per Simon, 4/27/99 - call parent _write. <d62062>
698      if (! Util.javaQualifiedName(parent).equals ("java.io.Serializable")) // <d60929>
699          stream.println(indent + Util.helperName (parent, true) + "._write (ostream, value);"); // <d60929> <d61056> <d62062>
700    }
701
702    Vector vMembers = ((ValueEntry) entry ).state ();
703    int noOfMembers = vMembers == null ? 0 : vMembers.size ();
704    for (int k = 0; k < noOfMembers; k++)
705    {
706      TypedefEntry member = (TypedefEntry)((InterfaceState)vMembers.elementAt (k)).entry;
707      String memberName = member.name ();
708      SymtabEntry mType = member.type ();
709
710      if (mType instanceof PrimitiveEntry ||
711          mType instanceof TypedefEntry   ||
712          mType instanceof SequenceEntry  ||
713          mType instanceof StringEntry    ||
714          !member.arrayInfo ().isEmpty ())
715        index = ((JavaGenerator)member.generator ()).write (index, indent, name + '.' + memberName, member, stream);
716      else
717        stream.println (indent + Util.helperName (mType, true) + // <d61056>
718                              ".write (ostream, " + name + '.' + memberName + ");");
719    }
720
721    return index;
722  } // write
723
724  /**
725   *
726   **/
727  protected void writeAbstract ()
728  {
729    stream.print ("public interface " + v.name ());
730
731    // workaround: if the abstract value type does not have any parent, a vector
732    // containing ValueBase should be returned instead of an empty vector
733    if (v.derivedFrom ().size () == 0)
734      stream.print (" extends org.omg.CORBA.portable.ValueBase"); // <d60929>
735    else
736    {
737      SymtabEntry parent;
738      // list the values the abstract value type inherits
739      for (int i = 0; i < v.derivedFrom ().size (); i++)
740      {
741        if (i == 0)
742           stream.print (" extends ");
743        else
744           stream.print (", ");
745        parent = (SymtabEntry) v.derivedFrom ().elementAt (i);
746        stream.print (Util.javaName (parent));
747      }
748    }
749
750    // list the interface the abstract value type supports
751    if (v.supports ().size () > 0)
752    {
753      stream.print (", ");
754      SymtabEntry intf = (SymtabEntry) v.supports ().elementAt (0);
755      stream.print (Util.javaName (intf));
756    }
757    stream.println ();
758    stream.println ("{");
759  }
760
761  protected int emit = 0;
762  protected Factories factories   = null;
763  protected Hashtable  symbolTable = null;
764  protected ValueEntry v = null;
765  protected PrintWriter stream = null;
766  protected boolean explicitDefaultInit = false; // <d57067 - klr>
767} // class ValueGen
768