KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > coach > idltree > IdlUnion


1 /***************************************************************************/
2 /* COACH: Component Based Open Source Architecture for */
3 /* Distributed Telecom Applications */
4 /* See: http://www.objectweb.org/ */
5 /* */
6 /* Copyright (C) 2003 Lucent Technologies Nederland BV */
7 /* Bell Labs Advanced Technologies - EMEA */
8 /* */
9 /* Initial developer(s): Harold Batteram */
10 /* */
11 /* This library is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public */
13 /* License as published by the Free Software Foundation; either */
14 /* version 2.1 of the License, or (at your option) any later version. */
15 /* */
16 /* This library is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
19 /* Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public */
22 /* License along with this library; if not, write to the Free Software */
23 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
24 /***************************************************************************/
25 package org.coach.idltree;
26
27 import org.w3c.dom.Node JavaDoc;
28 import java.util.*;
29 import java.io.*;
30 import java.lang.reflect.*;
31 import org.omg.CORBA.ORB JavaDoc;
32 import org.omg.CORBA.TypeCode JavaDoc;
33 import org.omg.CORBA.Any JavaDoc;
34 import org.omg.CORBA.TCKind JavaDoc;
35
36 /**
37  * The class IdlUnion represents an CORBA IDL union value. Instances are created through one
38  * of the create() factory methods in IdlNode.
39  * An IdlUnion object has one child nodes representing union member.
40  *
41  * @author <a HREF="mailto:batteram@lucent.com">Harold Batteram</a> <b>Lucent Technologies</b>
42  */

43 public class IdlUnion extends IdlNode implements IdlWritable {
44     protected String JavaDoc[] members;
45     protected String JavaDoc[] tags;
46     protected transient TypeCode JavaDoc[] memberTc;
47     protected transient TypeCode JavaDoc discTc;
48     protected String JavaDoc disc;
49     protected int index = -1;
50     protected int defaultIndex = 0;
51     protected transient Any JavaDoc[] anyTags;
52
53     protected IdlUnion() {
54         isLeaf = false;
55         setUserObject(this);
56     }
57         
58     protected IdlUnion(Any JavaDoc any) {
59         this();
60         try {
61             setNode(any);
62         } catch (Exception JavaDoc e) {
63             e.printStackTrace();
64         }
65     }
66         
67     protected IdlUnion(TypeCode JavaDoc tc) {
68         this();
69         setNode(tc);
70     }
71     
72     protected void setNode(TypeCode JavaDoc tc) {
73         try {
74             this.tc = tc;
75             if (tc.kind().value() == TCKind._tk_union) {
76                 id = tc.id();
77                 type = "union " + id;
78                 init(tc);
79                 value = tags[index];
80                 IdlNode m = create(memberTc[index]);
81                 m.field = members[index];
82                 removeAllChildren();
83                 add(m);
84             } else if (tc.kind().value() == TCKind._tk_alias) {
85                 id = tc.id();
86                 type = id;
87                 TypeCode JavaDoc stc = tc.content_type();
88                 while (stc.kind().value() == TCKind._tk_alias) {
89                     stc = stc.content_type();
90                 }
91                 if (stc.kind().value() != TCKind._tk_union) {
92                     throw new RuntimeException JavaDoc("Union type expected");
93                 }
94                 init(stc);
95                 value = tags[index];
96                 IdlNode m = create(memberTc[index]);
97                 m.field = members[index];
98                 removeAllChildren();
99                 add(m);
100             } else {
101                 throw new RuntimeException JavaDoc("Union type expected");
102             }
103         } catch (Exception JavaDoc e) {
104             e.printStackTrace();
105         }
106     }
107
108     protected void init(TypeCode JavaDoc tc) {
109         try {
110             if (members == null) {
111                 members = getMembers(tc);
112                 discTc = tc.discriminator_type();
113                 memberTc = new TypeCode JavaDoc[members.length];
114                 tags = new String JavaDoc[members.length];
115                 anyTags = new Any JavaDoc[members.length];
116                 for (int i = 0; i < members.length; i++) {
117                     memberTc[i] = tc.member_type(i);
118                     tags[i] = getDiscriminatorLabel(tc.member_label(i));
119                     anyTags[i] = tc.member_label(i);
120                 }
121                 defaultIndex = tc.default_index();
122                 if (defaultIndex < 0) {
123                     // If there is no explicit default, use the first member
124
defaultIndex = 0;
125                 } else {
126                     anyTags[defaultIndex] = getDefaultValue(discTc);
127                 }
128                 index = defaultIndex;
129             }
130         } catch (Exception JavaDoc e) {
131             e.printStackTrace();
132         }
133     }
134
135     protected void setNode(Any JavaDoc any) {
136         try {
137             setNode(any.type());
138                 
139             org.omg.CORBA.portable.InputStream JavaDoc in = any.create_input_stream();
140             // first read the discriminator into an any
141
Any JavaDoc discAny = orb.create_any();
142             discAny.type(discTc);
143             discAny.read_value(in, discTc);
144             
145             // obtain the tag label for the discriminator
146
String JavaDoc label = getDiscriminatorLabel(discAny);
147             if (label == null) {
148                 throw new RuntimeException JavaDoc("Uninitialized union");
149             }
150             
151             // find which index belongs to the discriminator label
152
index = defaultIndex;
153             for (int i = 0; i < tags.length; i++) {
154                 if (label.equals(tags[i])) {
155                     index = i;
156                     break;
157                 }
158             }
159
160             // now read the member from the input stream
161
Any JavaDoc memberAny = orb.create_any();
162             memberAny.read_value(in, memberTc[index]);
163             IdlNode m = create(memberAny);
164             m.field = members[index];
165             value = tags[index];
166             removeAllChildren();
167             add(m);
168         } catch (Exception JavaDoc e) {
169             e.printStackTrace();
170         }
171     }
172
173     /**
174      * Return the list of member names for this union.
175      *
176      * @return The list of member names for this union.
177      */

178     public String JavaDoc[] getMembers() {
179         return members;
180     }
181     
182     /**
183      * Return the list of tag names for this union.
184      *
185      * @return The list of tag names for this union.
186      */

187     public String JavaDoc[] getTags() {
188         return tags;
189     }
190
191     /**
192      * Return the current tag name for this union.
193      *
194      * @return The current tag name for this union.
195      */

196     public String JavaDoc getTag() {
197         return tags[index];
198     }
199     
200     /**
201      * Return the current member name for this union.
202      *
203      * @return The current member name for this union.
204      */

205     public String JavaDoc getMemberName() {
206         return members[index];
207     }
208
209     /**
210      * Return the current meber as an IdlNode for this union.
211      *
212      * @return The current meber as an IdlNode for this union.
213      */

214     public IdlNode getMember() {
215         try {
216             return (IdlNode)getChildAt(0);
217         } catch (Exception JavaDoc e) {
218             e.printStackTrace();
219         }
220         return null;
221     }
222         
223     /**
224      * Return the current tag index number for this union.
225      *
226      * @return The current tag index number for this union.
227      */

228     public int getIndex() {
229         return index;
230     }
231
232     /**
233      * Sets the curent union member from the given tag index number.
234      *
235      * @param The tag index number for this union.
236      */

237     public void setIndex(int i) {
238         try {
239             if (i < 0 || i >= tags.length) {
240                 throw new RuntimeException JavaDoc("index out of range");
241             }
242             value = tags[i];
243             if (value.equals("default")) {
244                 index = defaultIndex;
245             } else {
246                 index = i;
247             }
248             IdlNode n = IdlNode.create(memberTc[index]);
249             n.field = members[index];
250             removeAllChildren();
251             add(n);
252         } catch (Throwable JavaDoc t) {
253             t.printStackTrace();
254         }
255     }
256     
257     /**
258      * Returns the current value as a CORBA Any value.
259      *
260      * @return The current value as a CORBA Any.
261      */

262     public Any JavaDoc toAny() {
263         try {
264             if (index < 0) {
265                 throw new RuntimeException JavaDoc("Uninitialized union");
266             }
267             Any JavaDoc any = orb.create_any();
268             any.type(tc);
269             org.omg.CORBA.portable.OutputStream JavaDoc out = any.create_output_stream();
270             // write the discriminator tag value for the current index
271
anyTags[index].write_value(out);
272             // write the member
273
((IdlNode)getChildAt(0)).toAny().write_value(out);
274             any.read_value(out.create_input_stream(), tc);
275             return any;
276         } catch (Throwable JavaDoc e) {
277             e.printStackTrace();
278         }
279         return null;
280     }
281     
282     /**
283      * Returns the label tag contained in an any as a string.
284      * By convention, an octet with value 0 is used as the default label.
285      */

286     private String JavaDoc getDiscriminatorLabel(Any JavaDoc any) {
287         try {
288             switch (any.type().kind().value()) {
289                 case TCKind._tk_short: {
290                     return "" + any.extract_short();
291                 }
292                 case TCKind._tk_ushort: {
293                     return "" + any.extract_ushort();
294                 }
295                 case TCKind._tk_long: {
296                     return "" + any.extract_long();
297                 }
298                 case TCKind._tk_ulong: {
299                     return "" + any.extract_ulong();
300                 }
301                 case TCKind._tk_boolean: {
302                     return "" + any.extract_boolean();
303                 }
304                 case TCKind._tk_char: {
305                     return "" + any.extract_char();
306                 }
307                 case TCKind._tk_wchar: {
308                     return "" + any.extract_wchar();
309                 }
310                 case TCKind._tk_octet: {
311                     String JavaDoc v = "" + any.extract_octet();
312                     if (v.equals("0")) {
313                         return "default";
314                     } else {
315                         return v;
316                     }
317                 }
318                 case TCKind._tk_enum: {
319                     org.omg.CORBA.portable.InputStream JavaDoc in = any.create_input_stream();
320                     int v = in.read_ulong();
321                     return any.type().member_name(v);
322                 }
323             }
324         } catch (Exception JavaDoc e) {
325             e.printStackTrace();
326         }
327         return null;
328     }
329
330     /**
331      * Writes the value to a CORBA outputstream.
332      *
333      * @param is The outputstream to write to.
334      */

335     public void write(org.omg.CORBA.portable.OutputStream JavaDoc os) {
336         try {
337             ((IdlNode)getChildAt(0)).write(os);
338         } catch (Exception JavaDoc e) {
339             e.printStackTrace();
340         }
341     }
342
343     /**
344      * Reads the value from a CORBA inputstream.
345      *
346      * @param is The inputstream to read from.
347      */

348     public void read(org.omg.CORBA.portable.InputStream JavaDoc is) {
349         try {
350             ((IdlNode)getChildAt(0)).read(is);
351         } catch (Exception JavaDoc e) {
352             e.printStackTrace();
353         }
354     }
355         
356     /**
357      * Find a valid discriminitor value for the default label. This value is the first value
358      * in the range of possible discriminator values that is not used as a tag.
359      * Note that for enumerations there is no possible default value if all enumerators are used as tags.
360      * When the value is found, it is returned as an any.
361      */

362     private Any JavaDoc getDefaultValue(TypeCode JavaDoc dtc) {
363         try {
364             Any JavaDoc any = orb.create_any();
365             any.type(dtc);
366
367             switch (dtc.kind().value()) {
368                 case TCKind._tk_short: {
369                     for (int i = 0; i < 65536; i++) {
370                         if (!isLabel("" + i)) {
371                             any.insert_short((short)i);
372                             return any;
373                         }
374                     }
375                     throw new RuntimeException JavaDoc("no valid default value found");
376                 }
377                 case TCKind._tk_ushort: {
378                     for (int i = 0; i < 65536; i++) {
379                         if (!isLabel("" + i)) {
380                             any.insert_ushort((short)i);
381                             return any;
382                         }
383                     }
384                     throw new RuntimeException JavaDoc("no valid default value found");
385                 }
386                 case TCKind._tk_long: {
387                     for (int i = 0; i < 2147483647; i++) {
388                         if (!isLabel("" + i)) {
389                             any.insert_long(i);
390                             return any;
391                         }
392                     }
393                     throw new RuntimeException JavaDoc("no valid default value found");
394                 }
395                 case TCKind._tk_ulong: {
396                     for (int i = 0; i < 2147483647; i++) {
397                         if (!isLabel("" + i)) {
398                             any.insert_ulong(i);
399                             return any;
400                         }
401                     }
402                     throw new RuntimeException JavaDoc("no valid default value found");
403                 }
404                 case TCKind._tk_boolean: {
405                     if (!isLabel("TRUE")) {
406                         any.insert_boolean(true);
407                         return any;
408                     } else {
409                         any.insert_boolean(false);
410                         return any;
411                     }
412                 }
413                 case TCKind._tk_char: {
414                     for (int i = 0; i < 256; i++) {
415                         if (!isLabel(new Character JavaDoc((char)i).toString())) {
416                             any.insert_char((char)i);
417                             return any;
418                         }
419                     }
420                     throw new RuntimeException JavaDoc("no valid default value found");
421                 }
422                 case TCKind._tk_wchar: {
423                     for (int i = 0; i < 256; i++) {
424                         if (!isLabel(new Character JavaDoc((char)i).toString())) {
425                             any.insert_wchar((char)i);
426                             return any;
427                         }
428                     }
429                     throw new RuntimeException JavaDoc("no valid default value found");
430                 }
431                 case TCKind._tk_enum: {
432                     String JavaDoc[] eMembers = new String JavaDoc[dtc.member_count()];
433                     for (int i = 0; i < eMembers.length; i++) {
434                         eMembers[i] = dtc.member_name(i);
435                     }
436                     for (int i = 0; i < eMembers.length; i++) {
437                         if (!isLabel(eMembers[i])) {
438                             org.omg.CORBA.portable.OutputStream JavaDoc out = any.create_output_stream();
439                             out.write_ulong(i);
440                             any.read_value(out.create_input_stream(), dtc);
441                             return any;
442                         }
443                     }
444                     throw new RuntimeException JavaDoc("no valid default value found");
445                 }
446             }
447         } catch (Exception JavaDoc e) {
448             e.printStackTrace();
449         }
450         return null;
451     }
452     
453     private boolean isLabel(String JavaDoc label) {
454         for (int i = 0; i < tags.length; i++) {
455             if (tags[i].equals(label)) {
456                 return true;
457             }
458         }
459         return false;
460     }
461     
462     private String JavaDoc[] getMembers(TypeCode JavaDoc mtc) {
463         try {
464             String JavaDoc[] members = new String JavaDoc[mtc.member_count()];
465             for (int i = 0; i < members.length; i++) {
466                 members[i] = mtc.member_name(i);
467             }
468             return members;
469         } catch (Exception JavaDoc e) {
470         }
471         return null;
472     }
473     
474     // XML section
475

476     /**
477      * Create an IdlUnion from an Xml representation.
478      *
479      * The XML format example
480      * <pre>
481      * &lt;union id="IDL:example/MyEnumUnion:1.0"&gt;
482      * &lt;tag&gt;blue&lt;/tag&gt;
483      * &lt;member name="m1"&gt;
484      * &lt;string&gt;my member value&lt;/string&gt;
485      * &lt;/member&gt;
486      * &lt;/struct&gt;
487      * </pre>
488      *
489      * @param xml The XML string from which to create an IdlUnion instance.
490      */

491     public IdlUnion(String JavaDoc xml) {
492         this(XmlNode.getNode(xml));
493     }
494
495     IdlUnion(Node JavaDoc n) {
496         this();
497         try {
498             id = XmlNode.getId(n);
499             setNode(XmlNode.type(id));
500     
501             Node JavaDoc[] nodes = XmlNode.childElements(n);
502             if (nodes.length != 2) {
503                 throw new RuntimeException JavaDoc("Tag and member expected.");
504             }
505     
506             if (!nodes[0].getNodeName().toUpperCase().equals("TAG")) {
507                 throw new RuntimeException JavaDoc("Tag expected.");
508             }
509             
510             String JavaDoc tag = XmlNode.getText(nodes[0]);
511             for (int i = 0; i < tags.length; i++) {
512                 if (tags[i].equals(tag)) {
513                     index = i;
514                     break;
515                 }
516             }
517             if (index < 0) {
518                 throw new RuntimeException JavaDoc("invalid tag: " + tag);
519             }
520     
521             if (!nodes[1].getNodeName().toUpperCase().equals("MEMBER")) {
522                 throw new RuntimeException JavaDoc("Member expected.");
523             }
524     
525             String JavaDoc name = XmlNode.getName(nodes[1]);
526             if (!name.equals(members[index])) {
527                 throw new RuntimeException JavaDoc("tag does not match member name: " + name);
528             }
529             value = tag;
530             
531             IdlNode m = XmlNode.getIdlNode(memberTc[index], XmlNode.firstChildElement(nodes[1]));
532             m.setField(name);
533             removeAllChildren();
534             add(m);
535         } catch (Exception JavaDoc e) {
536             throw new RuntimeException JavaDoc(e.toString());
537         }
538     }
539     
540     /**
541      * Write the current value to an IdlWriter object.
542      *
543      * @param w The IdlWriter object to write the current value to.
544      */

545     public void write(IdlWriter w) {
546         write(this, w);
547     }
548
549     public static void write(IdlUnion n, IdlWriter w) {
550         w.write_start_union(n.getId());
551         w.write_union_tag(n.getTag());
552         w.write_start_member(n.getMemberName());
553         XmlNode.write(n.getMember(), w);
554         w.write_end_member();
555         w.write_end_union();
556     }
557 }
Popular Tags