001: /*
002: * Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.corba.se.impl.dynamicany;
027:
028: import org.omg.CORBA.TypeCode;
029: import org.omg.CORBA.TCKind;
030: import org.omg.CORBA.Any;
031: import org.omg.CORBA.TypeCodePackage.BadKind;
032: import org.omg.CORBA.TypeCodePackage.Bounds;
033: import org.omg.CORBA.portable.InputStream;
034: import org.omg.DynamicAny.*;
035: import org.omg.DynamicAny.DynAnyPackage.TypeMismatch;
036: import org.omg.DynamicAny.DynAnyPackage.InvalidValue;
037: import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode;
038:
039: import com.sun.corba.se.spi.orb.ORB;
040: import com.sun.corba.se.spi.logging.CORBALogDomains;
041: import com.sun.corba.se.impl.logging.ORBUtilSystemException;
042:
043: public class DynUnionImpl extends DynAnyConstructedImpl implements
044: DynUnion {
045: //
046: // Instance variables
047: //
048:
049: DynAny discriminator = null;
050: // index either points to the discriminator or the named member is it exists.
051: // The currently active member, which is of the same type as the discriminator.
052: DynAny currentMember = null;
053: int currentMemberIndex = NO_INDEX;
054:
055: //
056: // Constructors
057: //
058:
059: private DynUnionImpl() {
060: this (null, (Any) null, false);
061: }
062:
063: protected DynUnionImpl(ORB orb, Any any, boolean copyValue) {
064: // We can be sure that typeCode is of kind tk_union
065: super (orb, any, copyValue);
066: }
067:
068: protected DynUnionImpl(ORB orb, TypeCode typeCode) {
069: // We can be sure that typeCode is of kind tk_union
070: super (orb, typeCode);
071: }
072:
073: protected boolean initializeComponentsFromAny() {
074: try {
075: InputStream input = any.create_input_stream();
076: Any discriminatorAny = DynAnyUtil.extractAnyFromStream(
077: discriminatorType(), input, orb);
078: discriminator = DynAnyUtil.createMostDerivedDynAny(
079: discriminatorAny, orb, false);
080: currentMemberIndex = currentUnionMemberIndex(discriminatorAny);
081: Any memberAny = DynAnyUtil.extractAnyFromStream(
082: memberType(currentMemberIndex), input, orb);
083: currentMember = DynAnyUtil.createMostDerivedDynAny(
084: memberAny, orb, false);
085: components = new DynAny[] { discriminator, currentMember };
086: } catch (InconsistentTypeCode ictc) { // impossible
087: }
088: return true;
089: }
090:
091: // Sets the current position to zero.
092: // The discriminator value is set to a value consistent with the first named member
093: // of the union. That member is activated and (recursively) initialized to its default value.
094: protected boolean initializeComponentsFromTypeCode() {
095: //System.out.println(this + " initializeComponentsFromTypeCode");
096: try {
097: // We can be sure that memberCount() > 0 according to the IDL language spec
098: discriminator = DynAnyUtil.createMostDerivedDynAny(
099: memberLabel(0), orb, false);
100: index = 0;
101: currentMemberIndex = 0;
102: currentMember = DynAnyUtil.createMostDerivedDynAny(
103: memberType(0), orb);
104: components = new DynAny[] { discriminator, currentMember };
105: } catch (InconsistentTypeCode ictc) { // impossible
106: }
107: return true;
108: }
109:
110: //
111: // Convenience methods
112: //
113:
114: private TypeCode discriminatorType() {
115: TypeCode discriminatorType = null;
116: try {
117: discriminatorType = any.type().discriminator_type();
118: } catch (BadKind bad) {
119: }
120: return discriminatorType;
121: }
122:
123: private int memberCount() {
124: int memberCount = 0;
125: try {
126: memberCount = any.type().member_count();
127: } catch (BadKind bad) {
128: }
129: return memberCount;
130: }
131:
132: private Any memberLabel(int i) {
133: Any memberLabel = null;
134: try {
135: memberLabel = any.type().member_label(i);
136: } catch (BadKind bad) {
137: } catch (Bounds bounds) {
138: }
139: return memberLabel;
140: }
141:
142: private TypeCode memberType(int i) {
143: TypeCode memberType = null;
144: try {
145: memberType = any.type().member_type(i);
146: } catch (BadKind bad) {
147: } catch (Bounds bounds) {
148: }
149: return memberType;
150: }
151:
152: private String memberName(int i) {
153: String memberName = null;
154: try {
155: memberName = any.type().member_name(i);
156: } catch (BadKind bad) {
157: } catch (Bounds bounds) {
158: }
159: return memberName;
160: }
161:
162: private int defaultIndex() {
163: int defaultIndex = -1;
164: try {
165: defaultIndex = any.type().default_index();
166: } catch (BadKind bad) {
167: }
168: return defaultIndex;
169: }
170:
171: private int currentUnionMemberIndex(Any discriminatorValue) {
172: int memberCount = memberCount();
173: Any memberLabel;
174: for (int i = 0; i < memberCount; i++) {
175: memberLabel = memberLabel(i);
176: if (memberLabel.equal(discriminatorValue)) {
177: return i;
178: }
179: }
180: if (defaultIndex() != -1) {
181: return defaultIndex();
182: }
183: return NO_INDEX;
184: }
185:
186: protected void clearData() {
187: super .clearData();
188: discriminator = null;
189: // Necessary to guarantee OBJECT_NOT_EXIST in member()
190: currentMember.destroy();
191: currentMember = null;
192: currentMemberIndex = NO_INDEX;
193: }
194:
195: //
196: // DynAny interface methods
197: //
198:
199: // _REVISIT_ More efficient copy operation
200:
201: //
202: // DynUnion interface methods
203: //
204:
205: /**
206: * Returns the current discriminator value.
207: */
208: public org.omg.DynamicAny.DynAny get_discriminator() {
209: if (status == STATUS_DESTROYED) {
210: throw wrapper.dynAnyDestroyed();
211: }
212: return (checkInitComponents() ? discriminator : null);
213: }
214:
215: // Sets the discriminator of the DynUnion to the specified value.
216: // If the TypeCode of the parameter is not equivalent
217: // to the TypeCode of the unions discriminator, the operation raises TypeMismatch.
218: //
219: // Setting the discriminator to a value that is consistent with the currently
220: // active union member does not affect the currently active member.
221: // Setting the discriminator to a value that is inconsistent with the currently
222: // active member deactivates the member and activates the member that is consistent
223: // with the new discriminator value (if there is a member for that value)
224: // by initializing the member to its default value.
225: //
226: // If the discriminator value indicates a non-existent union member
227: // this operation sets the current position to 0
228: // (has_no_active_member returns true in this case).
229: // Otherwise the current position is set to 1 (has_no_active_member returns false and
230: // component_count returns 2 in this case).
231: public void set_discriminator(
232: org.omg.DynamicAny.DynAny newDiscriminator)
233: throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch {
234: if (status == STATUS_DESTROYED) {
235: throw wrapper.dynAnyDestroyed();
236: }
237: if (!newDiscriminator.type().equal(discriminatorType())) {
238: throw new TypeMismatch();
239: }
240: newDiscriminator = DynAnyUtil.convertToNative(newDiscriminator,
241: orb);
242: Any newDiscriminatorAny = getAny(newDiscriminator);
243: int newCurrentMemberIndex = currentUnionMemberIndex(newDiscriminatorAny);
244: if (newCurrentMemberIndex == NO_INDEX) {
245: clearData();
246: index = 0;
247: } else {
248: // _REVISIT_ Could possibly optimize here if we don't need to initialize components
249: checkInitComponents();
250: if (currentMemberIndex == NO_INDEX
251: || newCurrentMemberIndex != currentMemberIndex) {
252: clearData();
253: index = 1;
254: currentMemberIndex = newCurrentMemberIndex;
255: try {
256: currentMember = DynAnyUtil.createMostDerivedDynAny(
257: memberType(currentMemberIndex), orb);
258: } catch (InconsistentTypeCode ictc) {
259: }
260: discriminator = newDiscriminator;
261: components = new DynAny[] { discriminator,
262: currentMember };
263: representations = REPRESENTATION_COMPONENTS;
264: }
265: }
266: }
267:
268: // Sets the discriminator to a value that is consistent with the value
269: // of the default case of a union; it sets the current position to
270: // zero and causes component_count to return 2.
271: // Calling set_to_default_member on a union that does not have an explicit
272: // default case raises TypeMismatch.
273: public void set_to_default_member()
274: throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch {
275: if (status == STATUS_DESTROYED) {
276: throw wrapper.dynAnyDestroyed();
277: }
278: int defaultIndex = defaultIndex();
279: if (defaultIndex == -1) {
280: throw new TypeMismatch();
281: }
282: try {
283: clearData();
284: index = 1;
285: currentMemberIndex = defaultIndex;
286: currentMember = DynAnyUtil.createMostDerivedDynAny(
287: memberType(defaultIndex), orb);
288: components = new DynAny[] { discriminator, currentMember };
289: Any discriminatorAny = orb.create_any();
290: discriminatorAny.insert_octet((byte) 0);
291: discriminator = DynAnyUtil.createMostDerivedDynAny(
292: discriminatorAny, orb, false);
293: representations = REPRESENTATION_COMPONENTS;
294: } catch (InconsistentTypeCode ictc) {
295: }
296: }
297:
298: // Sets the discriminator to a value that does not correspond
299: // to any of the unions case labels.
300: // It sets the current position to zero and causes component_count to return 1.
301: // Calling set_to_no_active_member on a union that has an explicit default case
302: // or on a union that uses the entire range of discriminator values
303: // for explicit case labels raises TypeMismatch.
304: public void set_to_no_active_member()
305: throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch {
306: if (status == STATUS_DESTROYED) {
307: throw wrapper.dynAnyDestroyed();
308: }
309: // _REVISIT_ How does one check for "entire range of discriminator values"?
310: if (defaultIndex() != -1) {
311: throw new TypeMismatch();
312: }
313: checkInitComponents();
314: Any discriminatorAny = getAny(discriminator);
315: // erase the discriminators value so that it does not correspond
316: // to any of the unions case labels
317: discriminatorAny.type(discriminatorAny.type());
318: index = 0;
319: currentMemberIndex = NO_INDEX;
320: // Necessary to guarantee OBJECT_NOT_EXIST in member()
321: currentMember.destroy();
322: currentMember = null;
323: components[0] = discriminator;
324: representations = REPRESENTATION_COMPONENTS;
325: }
326:
327: // Returns true if the union has no active member
328: // (that is, the unions value consists solely of its discriminator because the
329: // discriminator has a value that is not listed as an explicit case label).
330: // Calling this operation on a union that has a default case returns false.
331: // Calling this operation on a union that uses the entire range of discriminator
332: // values for explicit case labels returns false.
333: public boolean has_no_active_member() {
334: if (status == STATUS_DESTROYED) {
335: throw wrapper.dynAnyDestroyed();
336: }
337: // _REVISIT_ How does one check for "entire range of discriminator values"?
338: if (defaultIndex() != -1) {
339: return false;
340: }
341: checkInitComponents();
342: return (checkInitComponents() ? (currentMemberIndex == NO_INDEX)
343: : false);
344: }
345:
346: public org.omg.CORBA.TCKind discriminator_kind() {
347: if (status == STATUS_DESTROYED) {
348: throw wrapper.dynAnyDestroyed();
349: }
350: return discriminatorType().kind();
351: }
352:
353: // Returns the currently active member.
354: // If the union has no active member, the operation raises InvalidValue.
355: // Note that the returned reference remains valid only for as long
356: // as the currently active member does not change.
357: // Using the returned reference beyond the life time
358: // of the currently active member raises OBJECT_NOT_EXIST.
359: public org.omg.DynamicAny.DynAny member()
360: throws org.omg.DynamicAny.DynAnyPackage.InvalidValue {
361: if (status == STATUS_DESTROYED) {
362: throw wrapper.dynAnyDestroyed();
363: }
364: if (!checkInitComponents() || currentMemberIndex == NO_INDEX)
365: throw new InvalidValue();
366: return currentMember;
367: }
368:
369: // Returns the name of the currently active member.
370: // If the unions TypeCode does not contain a member name for the currently active member,
371: // the operation returns an empty string.
372: // Calling member_name on a union without an active member raises InvalidValue.
373: public String member_name()
374: throws org.omg.DynamicAny.DynAnyPackage.InvalidValue {
375: if (status == STATUS_DESTROYED) {
376: throw wrapper.dynAnyDestroyed();
377: }
378: if (!checkInitComponents() || currentMemberIndex == NO_INDEX)
379: throw new InvalidValue();
380: String memberName = memberName(currentMemberIndex);
381: return (memberName == null ? "" : memberName);
382: }
383:
384: // Returns the TCKind value of the TypeCode of the currently active member.
385: // If the union has no active member, the operation raises InvalidValue.
386: public org.omg.CORBA.TCKind member_kind()
387: throws org.omg.DynamicAny.DynAnyPackage.InvalidValue {
388: if (status == STATUS_DESTROYED) {
389: throw wrapper.dynAnyDestroyed();
390: }
391: if (!checkInitComponents() || currentMemberIndex == NO_INDEX)
392: throw new InvalidValue();
393: return memberType(currentMemberIndex).kind();
394: }
395: }
|