1 /* gnuDynUnion.java --
2    Copyright (C) 2005 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package gnu.CORBA.DynAn;
40 
41 import gnu.CORBA.Unexpected;
42 
43 import org.omg.CORBA.Any;
44 import org.omg.CORBA.MARSHAL;
45 import org.omg.CORBA.ORB;
46 import org.omg.CORBA.TCKind;
47 import org.omg.CORBA.TypeCode;
48 import org.omg.CORBA.TypeCodePackage.BadKind;
49 import org.omg.CORBA.portable.InputStream;
50 import org.omg.CORBA.portable.OutputStream;
51 import org.omg.DynamicAny.DynAny;
52 import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode;
53 import org.omg.DynamicAny.DynAnyPackage.InvalidValue;
54 import org.omg.DynamicAny.DynAnyPackage.TypeMismatch;
55 import org.omg.DynamicAny.DynUnion;
56 
57 import java.io.Serializable;
58 
59 /**
60  * Implementation of DynUnion.
61  *
62  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
63  */
64 public class gnuDynUnion
65   extends DivideableAny
66   implements DynUnion, Serializable, ValueChangeListener
67 {
68   /**
69    * Use serialVersionUID for interoperability.
70    */
71   private static final long serialVersionUID = 1;
72 
73   /**
74    * The discrimintor of this union.
75    */
76   DynAny discriminator;
77 
78   /**
79    * The message string that occurs several times throwing exception.
80    */
81   static String NOAM = "No active member";
82 
83   /**
84    * Create a new instance with the given typecode.
85    *
86    * @param aType the final_type, must be final_type of the union.
87    */
gnuDynUnion(TypeCode oType, TypeCode aType, gnuDynAnyFactory aFactory, ORB anOrb )88   public gnuDynUnion(TypeCode oType, TypeCode aType, gnuDynAnyFactory aFactory,
89                      ORB anOrb
90                     )
91               throws InconsistentTypeCode
92   {
93     super(oType, aType, aFactory, anOrb);
94     try
95       {
96         discriminator =
97           factory.create_dyn_any_from_type_code(final_type.discriminator_type());
98 
99         ((AbstractAny) discriminator).listener = this;
100 
101         if (final_type.default_index() >= 0)
102           set_to_default_member();
103         else
104           set_to_no_active_member();
105       }
106     catch (Exception ex)
107       {
108         InconsistentTypeCode inc = new InconsistentTypeCode("discriminator");
109         inc.initCause(ex);
110         throw inc;
111       }
112   }
113 
114   /*
115    * (non-Javadoc)
116    *
117    * @see gnu.CORBA.DynAn.DivideableAny#to_any()
118    */
to_any()119   public Any to_any()
120   {
121     Any a = createAny();
122     OutputStream ou = a.create_output_stream();
123     discriminator.to_any().write_value(ou);
124     if (array.length == 2)
125       array [ 1 ].to_any().write_value(ou);
126     a.read_value(ou.create_input_stream(), final_type);
127     return a;
128   }
129 
130   /**
131    * Assign from another identical structure.
132    */
assign(DynAny from)133   public void assign(DynAny from)
134               throws TypeMismatch
135   {
136     checkType(official_type, from.type());
137     if (!(from instanceof DynUnion))
138       throw new TypeMismatch("DynUnion required");
139     else
140       {
141         try
142           {
143             DynUnion u = (DynUnion) from;
144             discriminator.assign(u.get_discriminator());
145             if (u.has_no_active_member())
146               {
147                 if (array.length != 1)
148                   array = new DynAny[] { discriminator };
149               }
150             else
151               {
152                 if (array.length != 2)
153                   array = new DynAny[] { discriminator, u.member().copy() };
154                 else
155                   array [ 1 ] = u.member().copy();
156               }
157           }
158         catch (InvalidValue e)
159           {
160             throw new Unexpected(e);
161           }
162       }
163     valueChanged();
164   }
165 
166   /** @inheritDoc */
copy()167   public DynAny copy()
168   {
169     try
170       {
171         gnuDynUnion other =
172           new gnuDynUnion(official_type, final_type, factory, orb);
173         other.discriminator = discriminator.copy();
174         ((AbstractAny) other.discriminator).listener = other;
175         if (array.length == 1)
176           {
177             other.array = new DynAny[] { other.discriminator };
178           }
179         else
180           {
181             other.array =
182               new DynAny[] { other.discriminator, array [ 1 ].copy() };
183           }
184         return other;
185       }
186     catch (InconsistentTypeCode ex)
187       {
188         throw new Unexpected(ex);
189       }
190   }
191 
192   /**
193    * Done via reading from stream.
194    */
from_any(Any an_any)195   public void from_any(Any an_any)
196                 throws TypeMismatch, InvalidValue
197   {
198     checkType(official_type, an_any.type());
199 
200     Any adis = createAny();
201     try
202       {
203         InputStream stream = an_any.create_input_stream();
204         adis.read_value(stream, final_type.discriminator_type());
205 
206         DynAny nd = factory.create_dyn_any(adis);
207 
208         set_discriminator(nd);
209         if (array.length == 2)
210           {
211             // Reusing the same Any <code>adis</code>.
212             adis.read_value(stream, array [ 1 ].type());
213             array [ 1 ].from_any(adis);
214           }
215       }
216     catch (InconsistentTypeCode it)
217       {
218         TypeMismatch t = new TypeMismatch();
219         t.initCause(it);
220         throw t;
221       }
222     catch (MARSHAL m)
223       {
224         InvalidValue t = new InvalidValue();
225         t.initCause(m);
226         throw t;
227       }
228     catch (BadKind b)
229       {
230         throw new Unexpected(b);
231       }
232     valueChanged();
233   }
234 
235   /** @inheritDoc */
discriminator_kind()236   public TCKind discriminator_kind()
237   {
238     return discriminator.type().kind();
239   }
240 
241   /** @inheritDoc */
get_discriminator()242   public DynAny get_discriminator()
243   {
244     return discriminator;
245   }
246 
247   /** @inheritDoc */
has_no_active_member()248   public boolean has_no_active_member()
249   {
250     return array.length == 1;
251   }
252 
253   /** @inheritDoc */
member_kind()254   public TCKind member_kind()
255                      throws InvalidValue
256   {
257     return member().type().kind();
258   }
259 
260   /**
261    * Get the name of the current variant of the union.
262    */
member_name()263   public String member_name()
264                      throws InvalidValue
265   {
266     if (array.length == 1)
267       throw new InvalidValue(NOAM);
268     try
269       {
270         Any da = discriminator.to_any();
271 
272 
273         // Get the discriminator variant.
274         for (int i = 0; i < final_type.member_count(); i++)
275           {
276             if (final_type.member_label(i).equal(da))
277               return final_type.member_name(i);
278           }
279         throw new InvalidValue(NOAM);
280       }
281     catch (Exception e)
282       {
283         InvalidValue t = new InvalidValue("Err");
284         t.initCause(e);
285         throw t;
286       }
287   }
288 
289   /** @inheritDoc */
member()290   public DynAny member()
291                 throws InvalidValue
292   {
293     if (array.length < 2)
294       throw new InvalidValue(NOAM);
295     else
296       return array [ 1 ];
297   }
298 
299   /**
300    * Set the union discriminator.
301    */
set_discriminator(DynAny aDiscriminator)302   public void set_discriminator(DynAny aDiscriminator)
303                          throws TypeMismatch
304   {
305     try
306       {
307         if (!aDiscriminator.type().equal(final_type.discriminator_type()))
308           throw new TypeMismatch("Wrong discriminator final_type for " +
309                                  final_type.name()
310                                 );
311 
312         // Seting the same discriminator value again should not change
313         // the fields of the current member.
314         if (!discriminator.equal(aDiscriminator))
315           {
316             discriminator.assign(aDiscriminator);
317             updateMember();
318           }
319         else
320           {
321             pos = array.length == 2 ? 1 : 0;
322           }
323       }
324     catch (Exception e)
325       {
326         TypeMismatch t = new TypeMismatch();
327         t.initCause(e);
328         throw t;
329       }
330   }
331 
332   /**
333    * Set to default member, if one exists.
334    */
set_to_default_member()335   public void set_to_default_member()
336                              throws TypeMismatch
337   {
338     try
339       {
340         int di = final_type.default_index();
341         if (di < 0)
342           throw new TypeMismatch("Union " + final_type.name() +
343                                  "has no default index"
344                                 );
345 
346         Any da = final_type.member_label(di);
347         discriminator.from_any(da);
348         updateMember();
349       }
350     catch (TypeMismatch m)
351       {
352         // This one OK.
353         throw m;
354       }
355     catch (Exception e)
356       {
357         TypeMismatch t = new TypeMismatch();
358         t.initCause(e);
359         throw t;
360       }
361   }
362 
363   /** @inheritDoc */
set_to_no_active_member()364   public void set_to_no_active_member()
365                                throws TypeMismatch
366   {
367     try
368       {
369         if (final_type.default_index() >= 0)
370           {
371             throw new TypeMismatch("Explicit default case defined.");
372           }
373       }
374     catch (BadKind ex)
375       {
376         // The default index is not set.
377       }
378     array = new DynAny[] { discriminator };
379     valueChanged();
380   }
381 
382   /**
383    * Update member, in accordance with discriminator value.
384    */
updateMember()385   public void updateMember()
386                     throws TypeMismatch
387   {
388     try
389       {
390         Any da = discriminator.to_any();
391 
392 
393         // Get the discriminator variant.
394         for (int i = 0; i < final_type.member_count(); i++)
395           {
396             if (final_type.member_label(i).equal(da))
397               {
398                 array =
399                   new DynAny[]
400                   {
401                     discriminator,
402                     factory.create_dyn_any_from_type_code(final_type.member_type(i))
403                   };
404                 pos = 1;
405                 valueChanged();
406                 return;
407               }
408           }
409       }
410     catch (Exception e)
411       {
412         TypeMismatch t = new TypeMismatch();
413         t.initCause(e);
414         throw t;
415       }
416 
417     // Discrimintator does not point to valid member.
418     array = new DynAny[] { discriminator };
419     pos = 0;
420     valueChanged();
421   }
422 
423   /**
424    * Called when the discriminator is changed.
425    */
changed()426   public void changed()
427   {
428     try
429       {
430         updateMember();
431       }
432     catch (TypeMismatch ex)
433       {
434         throw new Unexpected(ex);
435       }
436   }
437 }
438