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 
26 package com.sun.corba.se.impl.dynamicany;
27 
28 import org.omg.CORBA.TypeCode;
29 import org.omg.CORBA.TCKind;
30 import org.omg.CORBA.Any;
31 import org.omg.CORBA.TypeCodePackage.BadKind;
32 import org.omg.CORBA.TypeCodePackage.Bounds;
33 import org.omg.CORBA.portable.InputStream;
34 import org.omg.DynamicAny.*;
35 import org.omg.DynamicAny.DynAnyPackage.TypeMismatch;
36 import org.omg.DynamicAny.DynAnyPackage.InvalidValue;
37 import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode;
38 
39 import com.sun.corba.se.spi.orb.ORB ;
40 import com.sun.corba.se.spi.logging.CORBALogDomains ;
41 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
42 
43 public 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 
DynUnionImpl()59     private DynUnionImpl() {
60         this(null, (Any)null, false);
61     }
62 
DynUnionImpl(ORB orb, Any any, boolean copyValue)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 
DynUnionImpl(ORB orb, TypeCode typeCode)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 
initializeComponentsFromAny()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.
initializeComponentsFromTypeCode()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 
discriminatorType()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 
memberCount()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 
memberLabel(int i)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 
memberType(int i)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 
memberName(int i)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 
defaultIndex()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 
currentUnionMemberIndex(Any discriminatorValue)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 
clearData()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     */
get_discriminator()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).
set_discriminator(org.omg.DynamicAny.DynAny newDiscriminator)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.
set_to_default_member()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.
set_to_no_active_member()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.
has_no_active_member()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 
discriminator_kind()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.
member()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.
member_name()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.
member_kind()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