DynUnionImpl.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 2000, 2003, 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 26package com.sun.corba.se.impl.dynamicany; 27 28import org.omg.CORBA.TypeCode; 29import org.omg.CORBA.TCKind; 30import org.omg.CORBA.Any; 31import org.omg.CORBA.TypeCodePackage.BadKind; 32import org.omg.CORBA.TypeCodePackage.Bounds; 33import org.omg.CORBA.portable.InputStream; 34import org.omg.DynamicAny.*; 35import org.omg.DynamicAny.DynAnyPackage.TypeMismatch; 36import org.omg.DynamicAny.DynAnyPackage.InvalidValue; 37import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode; 38 39import com.sun.corba.se.spi.orb.ORB ; 40import com.sun.corba.se.spi.logging.CORBALogDomains ; 41import com.sun.corba.se.impl.logging.ORBUtilSystemException ; 42 43public class DynUnionImpl extends DynAnyConstructedImpl implements DynUnion 44{ 45 // 46 // Instance variables 47 // 48 49 DynAny discriminator = null; 50 // index either points to the discriminator or the named member is it exists. 51 // The currently active member, which is of the same type as the discriminator. 52 DynAny currentMember = null; 53 int currentMemberIndex = NO_INDEX; 54 55 // 56 // Constructors 57 // 58 59 private DynUnionImpl() { 60 this(null, (Any)null, false); 61 } 62 63 protected DynUnionImpl(ORB orb, Any any, boolean copyValue) { 64 // We can be sure that typeCode is of kind tk_union 65 super(orb, any, copyValue); 66 } 67 68 protected DynUnionImpl(ORB orb, TypeCode typeCode) { 69 // We can be sure that typeCode is of kind tk_union 70 super(orb, typeCode); 71 } 72 73 protected boolean initializeComponentsFromAny() { 74 try { 75 InputStream input = any.create_input_stream(); 76 Any discriminatorAny = DynAnyUtil.extractAnyFromStream(discriminatorType(), input, orb); 77 discriminator = DynAnyUtil.createMostDerivedDynAny(discriminatorAny, orb, false); 78 currentMemberIndex = currentUnionMemberIndex(discriminatorAny); 79 Any memberAny = DynAnyUtil.extractAnyFromStream(memberType(currentMemberIndex), input, orb); 80 currentMember = DynAnyUtil.createMostDerivedDynAny(memberAny, orb, false); 81 components = new DynAny[] {discriminator, currentMember}; 82 } catch (InconsistentTypeCode ictc) { // impossible 83 } 84 return true; 85 } 86 87 // Sets the current position to zero. 88 // The discriminator value is set to a value consistent with the first named member 89 // of the union. That member is activated and (recursively) initialized to its default value. 90 protected boolean initializeComponentsFromTypeCode() { 91 //System.out.println(this + " initializeComponentsFromTypeCode"); 92 try { 93 // We can be sure that memberCount() > 0 according to the IDL language spec 94 discriminator = DynAnyUtil.createMostDerivedDynAny(memberLabel(0), orb, false); 95 index = 0; 96 currentMemberIndex = 0; 97 currentMember = DynAnyUtil.createMostDerivedDynAny(memberType(0), orb); 98 components = new DynAny[] {discriminator, currentMember}; 99 } catch (InconsistentTypeCode ictc) { // impossible 100 } 101 return true; 102 } 103 104 // 105 // Convenience methods 106 // 107 108 private TypeCode discriminatorType() { 109 TypeCode discriminatorType = null; 110 try { 111 discriminatorType = any.type().discriminator_type(); 112 } catch (BadKind bad) { 113 } 114 return discriminatorType; 115 } 116 117 private int memberCount() { 118 int memberCount = 0; 119 try { 120 memberCount = any.type().member_count(); 121 } catch (BadKind bad) { 122 } 123 return memberCount; 124 } 125 126 private Any memberLabel(int i) { 127 Any memberLabel = null; 128 try { 129 memberLabel = any.type().member_label(i); 130 } catch (BadKind bad) { 131 } catch (Bounds bounds) { 132 } 133 return memberLabel; 134 } 135 136 private TypeCode memberType(int i) { 137 TypeCode memberType = null; 138 try { 139 memberType = any.type().member_type(i); 140 } catch (BadKind bad) { 141 } catch (Bounds bounds) { 142 } 143 return memberType; 144 } 145 146 private String memberName(int i) { 147 String memberName = null; 148 try { 149 memberName = any.type().member_name(i); 150 } catch (BadKind bad) { 151 } catch (Bounds bounds) { 152 } 153 return memberName; 154 } 155 156 private int defaultIndex() { 157 int defaultIndex = -1; 158 try { 159 defaultIndex = any.type().default_index(); 160 } catch (BadKind bad) { 161 } 162 return defaultIndex; 163 } 164 165 private int currentUnionMemberIndex(Any discriminatorValue) { 166 int memberCount = memberCount(); 167 Any memberLabel; 168 for (int i=0; i<memberCount; i++) { 169 memberLabel = memberLabel(i); 170 if (memberLabel.equal(discriminatorValue)) { 171 return i; 172 } 173 } 174 if (defaultIndex() != -1) { 175 return defaultIndex(); 176 } 177 return NO_INDEX; 178 } 179 180 protected void clearData() { 181 super.clearData(); 182 discriminator = null; 183 // Necessary to guarantee OBJECT_NOT_EXIST in member() 184 currentMember.destroy(); 185 currentMember = null; 186 currentMemberIndex = NO_INDEX; 187 } 188 189 // 190 // DynAny interface methods 191 // 192 193 // _REVISIT_ More efficient copy operation 194 195 // 196 // DynUnion interface methods 197 // 198 199 /** 200 * Returns the current discriminator value. 201 */ 202 public org.omg.DynamicAny.DynAny get_discriminator () { 203 if (status == STATUS_DESTROYED) { 204 throw wrapper.dynAnyDestroyed() ; 205 } 206 return (checkInitComponents() ? discriminator : null); 207 } 208 209 // Sets the discriminator of the DynUnion to the specified value. 210 // If the TypeCode of the parameter is not equivalent 211 // to the TypeCode of the unions discriminator, the operation raises TypeMismatch. 212 // 213 // Setting the discriminator to a value that is consistent with the currently 214 // active union member does not affect the currently active member. 215 // Setting the discriminator to a value that is inconsistent with the currently 216 // active member deactivates the member and activates the member that is consistent 217 // with the new discriminator value (if there is a member for that value) 218 // by initializing the member to its default value. 219 // 220 // If the discriminator value indicates a non-existent union member 221 // this operation sets the current position to 0 222 // (has_no_active_member returns true in this case). 223 // Otherwise the current position is set to 1 (has_no_active_member returns false and 224 // component_count returns 2 in this case). 225 public void set_discriminator (org.omg.DynamicAny.DynAny newDiscriminator) 226 throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch 227 { 228 if (status == STATUS_DESTROYED) { 229 throw wrapper.dynAnyDestroyed() ; 230 } 231 if ( ! newDiscriminator.type().equal(discriminatorType())) { 232 throw new TypeMismatch(); 233 } 234 newDiscriminator = DynAnyUtil.convertToNative(newDiscriminator, orb); 235 Any newDiscriminatorAny = getAny(newDiscriminator); 236 int newCurrentMemberIndex = currentUnionMemberIndex(newDiscriminatorAny); 237 if (newCurrentMemberIndex == NO_INDEX) { 238 clearData(); 239 index = 0; 240 } else { 241 // _REVISIT_ Could possibly optimize here if we don't need to initialize components 242 checkInitComponents(); 243 if (currentMemberIndex == NO_INDEX || newCurrentMemberIndex != currentMemberIndex) { 244 clearData(); 245 index = 1; 246 currentMemberIndex = newCurrentMemberIndex; 247 try { 248 currentMember = DynAnyUtil.createMostDerivedDynAny(memberType(currentMemberIndex), orb); 249 } catch (InconsistentTypeCode ictc) {} 250 discriminator = newDiscriminator; 251 components = new DynAny[] { discriminator, currentMember }; 252 representations = REPRESENTATION_COMPONENTS; 253 } 254 } 255 } 256 257 // Sets the discriminator to a value that is consistent with the value 258 // of the default case of a union; it sets the current position to 259 // zero and causes component_count to return 2. 260 // Calling set_to_default_member on a union that does not have an explicit 261 // default case raises TypeMismatch. 262 public void set_to_default_member () 263 throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch 264 { 265 if (status == STATUS_DESTROYED) { 266 throw wrapper.dynAnyDestroyed() ; 267 } 268 int defaultIndex = defaultIndex(); 269 if (defaultIndex == -1) { 270 throw new TypeMismatch(); 271 } 272 try { 273 clearData(); 274 index = 1; 275 currentMemberIndex = defaultIndex; 276 currentMember = DynAnyUtil.createMostDerivedDynAny(memberType(defaultIndex), orb); 277 components = new DynAny[] {discriminator, currentMember}; 278 Any discriminatorAny = orb.create_any(); 279 discriminatorAny.insert_octet((byte)0); 280 discriminator = DynAnyUtil.createMostDerivedDynAny(discriminatorAny, orb, false); 281 representations = REPRESENTATION_COMPONENTS; 282 } catch (InconsistentTypeCode ictc) {} 283 } 284 285 // Sets the discriminator to a value that does not correspond 286 // to any of the unions case labels. 287 // It sets the current position to zero and causes component_count to return 1. 288 // Calling set_to_no_active_member on a union that has an explicit default case 289 // or on a union that uses the entire range of discriminator values 290 // for explicit case labels raises TypeMismatch. 291 public void set_to_no_active_member () 292 throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch 293 { 294 if (status == STATUS_DESTROYED) { 295 throw wrapper.dynAnyDestroyed() ; 296 } 297 // _REVISIT_ How does one check for "entire range of discriminator values"? 298 if (defaultIndex() != -1) { 299 throw new TypeMismatch(); 300 } 301 checkInitComponents(); 302 Any discriminatorAny = getAny(discriminator); 303 // erase the discriminators value so that it does not correspond 304 // to any of the unions case labels 305 discriminatorAny.type(discriminatorAny.type()); 306 index = 0; 307 currentMemberIndex = NO_INDEX; 308 // Necessary to guarantee OBJECT_NOT_EXIST in member() 309 currentMember.destroy(); 310 currentMember = null; 311 components[0] = discriminator; 312 representations = REPRESENTATION_COMPONENTS; 313 } 314 315 // Returns true if the union has no active member 316 // (that is, the unions value consists solely of its discriminator because the 317 // discriminator has a value that is not listed as an explicit case label). 318 // Calling this operation on a union that has a default case returns false. 319 // Calling this operation on a union that uses the entire range of discriminator 320 // values for explicit case labels returns false. 321 public boolean has_no_active_member () { 322 if (status == STATUS_DESTROYED) { 323 throw wrapper.dynAnyDestroyed() ; 324 } 325 // _REVISIT_ How does one check for "entire range of discriminator values"? 326 if (defaultIndex() != -1) { 327 return false; 328 } 329 checkInitComponents(); 330 return (checkInitComponents() ? (currentMemberIndex == NO_INDEX) : false); 331 } 332 333 public org.omg.CORBA.TCKind discriminator_kind () { 334 if (status == STATUS_DESTROYED) { 335 throw wrapper.dynAnyDestroyed() ; 336 } 337 return discriminatorType().kind(); 338 } 339 340 // Returns the currently active member. 341 // If the union has no active member, the operation raises InvalidValue. 342 // Note that the returned reference remains valid only for as long 343 // as the currently active member does not change. 344 // Using the returned reference beyond the life time 345 // of the currently active member raises OBJECT_NOT_EXIST. 346 public org.omg.DynamicAny.DynAny member () 347 throws org.omg.DynamicAny.DynAnyPackage.InvalidValue 348 { 349 if (status == STATUS_DESTROYED) { 350 throw wrapper.dynAnyDestroyed() ; 351 } 352 if ( ! checkInitComponents() || currentMemberIndex == NO_INDEX) 353 throw new InvalidValue(); 354 return currentMember; 355 } 356 357 // Returns the name of the currently active member. 358 // If the unions TypeCode does not contain a member name for the currently active member, 359 // the operation returns an empty string. 360 // Calling member_name on a union without an active member raises InvalidValue. 361 public String member_name () 362 throws org.omg.DynamicAny.DynAnyPackage.InvalidValue 363 { 364 if (status == STATUS_DESTROYED) { 365 throw wrapper.dynAnyDestroyed() ; 366 } 367 if ( ! checkInitComponents() || currentMemberIndex == NO_INDEX) 368 throw new InvalidValue(); 369 String memberName = memberName(currentMemberIndex); 370 return (memberName == null ? "" : memberName); 371 } 372 373 // Returns the TCKind value of the TypeCode of the currently active member. 374 // If the union has no active member, the operation raises InvalidValue. 375 public org.omg.CORBA.TCKind member_kind () 376 throws org.omg.DynamicAny.DynAnyPackage.InvalidValue 377 { 378 if (status == STATUS_DESTROYED) { 379 throw wrapper.dynAnyDestroyed() ; 380 } 381 if ( ! checkInitComponents() || currentMemberIndex == NO_INDEX) 382 throw new InvalidValue(); 383 return memberType(currentMemberIndex).kind(); 384 } 385} 386