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