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 Variants: 275 for (int i = 0; i < final_type.member_count(); i++) 276 { 277 if (final_type.member_label(i).equal(da)) 278 return final_type.member_name(i); 279 } 280 throw new InvalidValue(NOAM); 281 } 282 catch (Exception e) 283 { 284 InvalidValue t = new InvalidValue("Err"); 285 t.initCause(e); 286 throw t; 287 } 288 } 289 290 /** @inheritDoc */ member()291 public DynAny member() 292 throws InvalidValue 293 { 294 if (array.length < 2) 295 throw new InvalidValue(NOAM); 296 else 297 return array [ 1 ]; 298 } 299 300 /** 301 * Set the union discriminator. 302 */ set_discriminator(DynAny aDiscriminator)303 public void set_discriminator(DynAny aDiscriminator) 304 throws TypeMismatch 305 { 306 try 307 { 308 if (!aDiscriminator.type().equal(final_type.discriminator_type())) 309 throw new TypeMismatch("Wrong discriminator final_type for " + 310 final_type.name() 311 ); 312 313 // Seting the same discriminator value again should not change 314 // the fields of the current member. 315 if (!discriminator.equal(aDiscriminator)) 316 { 317 discriminator.assign(aDiscriminator); 318 updateMember(); 319 } 320 else 321 { 322 pos = array.length == 2 ? 1 : 0; 323 } 324 } 325 catch (Exception e) 326 { 327 TypeMismatch t = new TypeMismatch(); 328 t.initCause(e); 329 throw t; 330 } 331 } 332 333 /** 334 * Set to default member, if one exists. 335 */ set_to_default_member()336 public void set_to_default_member() 337 throws TypeMismatch 338 { 339 try 340 { 341 int di = final_type.default_index(); 342 if (di < 0) 343 throw new TypeMismatch("Union " + final_type.name() + 344 "has no default index" 345 ); 346 347 Any da = final_type.member_label(di); 348 discriminator.from_any(da); 349 updateMember(); 350 } 351 catch (TypeMismatch m) 352 { 353 // This one OK. 354 throw m; 355 } 356 catch (Exception e) 357 { 358 TypeMismatch t = new TypeMismatch(); 359 t.initCause(e); 360 throw t; 361 } 362 } 363 364 /** @inheritDoc */ set_to_no_active_member()365 public void set_to_no_active_member() 366 throws TypeMismatch 367 { 368 try 369 { 370 if (final_type.default_index() >= 0) 371 { 372 throw new TypeMismatch("Explicit default case defined."); 373 } 374 } 375 catch (BadKind ex) 376 { 377 // The default index is not set. 378 } 379 array = new DynAny[] { discriminator }; 380 valueChanged(); 381 } 382 383 /** 384 * Update member, in accordance with discriminator value. 385 */ updateMember()386 public void updateMember() 387 throws TypeMismatch 388 { 389 try 390 { 391 Any da = discriminator.to_any(); 392 393 394 // Get the discriminator variant. 395 Variants: 396 for (int i = 0; i < final_type.member_count(); i++) 397 { 398 if (final_type.member_label(i).equal(da)) 399 { 400 array = 401 new DynAny[] 402 { 403 discriminator, 404 factory.create_dyn_any_from_type_code(final_type.member_type(i)) 405 }; 406 pos = 1; 407 valueChanged(); 408 return; 409 } 410 } 411 } 412 catch (Exception e) 413 { 414 TypeMismatch t = new TypeMismatch(); 415 t.initCause(e); 416 throw t; 417 } 418 419 // Discrimintator does not point to valid member. 420 array = new DynAny[] { discriminator }; 421 pos = 0; 422 valueChanged(); 423 } 424 425 /** 426 * Called when the discriminator is changed. 427 */ changed()428 public void changed() 429 { 430 try 431 { 432 updateMember(); 433 } 434 catch (TypeMismatch ex) 435 { 436 throw new Unexpected(ex); 437 } 438 } 439 }