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