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