001: package org.jacorb.orb.dynany;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1997-2004 Gerald Brose, FU Berlin.
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: */
022:
023: import org.omg.DynamicAny.DynAnyPackage.*;
024: import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode;
025: import org.omg.DynamicAny.*;
026:
027: import org.apache.avalon.framework.logger.Logger;
028: import org.jacorb.orb.*;
029: import org.omg.CORBA.TCKind;
030:
031: /**
032: * CORBA DynUnion
033: *
034: * @author Gerald Brose
035: * @version $Id: DynUnion.java,v 1.29 2006/07/05 09:18:11 alphonse.bendt Exp $
036: */
037:
038: public final class DynUnion extends DynAny implements
039: org.omg.DynamicAny.DynUnion {
040: private org.omg.CORBA.Any discriminator;
041: private org.omg.DynamicAny.DynAny member;
042: private String memberName;
043: private int memberIndex;
044:
045: DynUnion(org.omg.DynamicAny.DynAnyFactory dynFactory,
046: org.omg.CORBA.TypeCode tc, org.omg.CORBA.ORB orb,
047: Logger logger) throws TypeMismatch {
048: super (dynFactory, orb, logger);
049:
050: org.omg.CORBA.TypeCode _type = TypeCode.originalType(tc);
051:
052: if (_type.kind() != org.omg.CORBA.TCKind.tk_union) {
053: throw new TypeMismatch();
054: }
055:
056: typeCode = _type;
057:
058: pos = 0;
059: limit = 2;
060:
061: try {
062: for (int i = 0; i < typeCode.member_count(); i++) {
063: discriminator = typeCode.member_label(i);
064:
065: if (discriminator.type().kind().value() != org.omg.CORBA.TCKind._tk_octet) {
066: break;
067: }
068: }
069:
070: // rare case when the union only has a default case label
071: if (discriminator.type().kind().value() == org.omg.CORBA.TCKind._tk_octet) {
072: try {
073: set_to_unlisted_label();
074: } catch (TypeMismatch e) {
075: throw unexpectedException(e);
076: }
077: }
078:
079: select_member();
080: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
081: throw unexpectedException(e);
082: } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
083: throw unexpectedException(e);
084: }
085: }
086:
087: /**
088: * Overrides from_any() in DynAny
089: */
090:
091: public void from_any(org.omg.CORBA.Any value) throws InvalidValue,
092: TypeMismatch {
093: checkDestroyed();
094: if (!type().equivalent(value.type())) {
095: throw new TypeMismatch();
096: }
097:
098: try {
099: typeCode = TypeCode.originalType(value.type());
100: super .from_any(value);
101:
102: limit = 2;
103: org.omg.CORBA.portable.InputStream is = value
104: .create_input_stream();
105:
106: discriminator = orb.create_any();
107: discriminator.type(type().discriminator_type());
108:
109: discriminator.read_value(is, type().discriminator_type());
110:
111: org.omg.CORBA.Any member_any = null;
112: for (int i = 0; i < type().member_count(); i++) {
113: if (type().member_label(i).equal(discriminator)) {
114: member_any = orb.create_any();
115: member_any.read_value(is, type().member_type(i));
116: memberName = type().member_name(i);
117: memberIndex = i;
118: break;
119: }
120: }
121:
122: if (member_any == null) {
123: int def_idx = type().default_index();
124: if (def_idx != -1) {
125: member_any = orb.create_any();
126: member_any.read_value(is, type().member_type(
127: def_idx));
128: memberName = type().member_name(def_idx);
129: memberIndex = def_idx;
130: }
131: }
132:
133: if (member_any != null) {
134: try {
135: member = dynFactory.create_dyn_any(member_any);
136: } catch (InconsistentTypeCode e) {
137: throw unexpectedException(e);
138: }
139: }
140: } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
141: throw unexpectedException(e);
142: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
143: throw unexpectedException(e);
144: }
145: }
146:
147: /**
148: * @return an Any that holds a copy of this union
149: */
150: public org.omg.CORBA.Any to_any() {
151: checkDestroyed();
152: final CDROutputStream out = new CDROutputStream(orb);
153:
154: try {
155: out.write_value(discriminator.type(), discriminator
156: .create_input_stream());
157:
158: out.write_value(member.type(), member.to_any()
159: .create_input_stream());
160:
161: org.omg.CORBA.Any out_any = orb.create_any();
162:
163: out_any.type(type());
164: final CDRInputStream in = new CDRInputStream(orb, out
165: .getBufferCopy());
166:
167: try {
168: out_any.read_value(in, type());
169: return out_any;
170: } finally {
171: in.close();
172: }
173: } finally {
174: out.close();
175: }
176: }
177:
178: /**
179: * Overrides component_count() in DynAny
180: */
181: public int component_count() {
182: if (has_no_active_member()) {
183: return 1;
184: }
185: return limit;
186: }
187:
188: /**
189: * Overrides next() in DynAny
190: */
191: public boolean next() {
192: checkDestroyed();
193: if (pos < component_count() - 1) {
194: pos++;
195: return true;
196: }
197: pos = -1;
198: return false;
199: }
200:
201: /**
202: * Overrides seek() in DynAny
203: */
204: public boolean seek(int index) {
205: checkDestroyed();
206: if (index < 0) {
207: pos = -1;
208: return false;
209: }
210: if (index < component_count()) {
211: pos = index;
212: return true;
213: }
214: pos = -1;
215: return false;
216: }
217:
218: /**
219: * Overrides equal() in DynAny
220: */
221: public boolean equal(org.omg.DynamicAny.DynAny dyn_any) {
222: checkDestroyed();
223: if (!type().equal(dyn_any.type())) {
224: return false;
225: }
226:
227: org.omg.DynamicAny.DynUnion other = DynUnionHelper
228: .narrow(dyn_any);
229:
230: if (!get_discriminator().equal(other.get_discriminator())) {
231: return false;
232: }
233:
234: if (!has_no_active_member()) {
235: // other must have the same here because we know the
236: // discriminators are equal
237:
238: try {
239: if (!member.equal(other.member())) {
240: return false;
241: }
242: } catch (Exception e) {
243: throw unexpectedException(e);
244: }
245: }
246: return true;
247: }
248:
249: /**
250: * @return the current discriminator value
251: */
252:
253: public org.omg.DynamicAny.DynAny get_discriminator() {
254: checkDestroyed();
255: try {
256: return dynFactory.create_dyn_any(discriminator);
257: } catch (InconsistentTypeCode e) {
258: throw unexpectedException(e);
259: }
260: }
261:
262: /**
263: * sets the discriminator to d
264: * @throws TypeMismatch if the TypeCode of the d parameter
265: * is not equivalent to the TypeCode of the union's discriminator
266: */
267:
268: public void set_discriminator(org.omg.DynamicAny.DynAny dynAny)
269: throws TypeMismatch {
270: checkDestroyed();
271: if (!dynAny.type().equivalent(discriminator.type())) {
272: throw new TypeMismatch();
273: }
274: discriminator = dynAny.to_any();
275: pos = 1;
276:
277: /* check if the new discriminator is consistent with the
278: currently active member. If not, select a new one */
279:
280: try {
281: if (memberIndex == typeCode.default_index()) {
282: // default member, only change the member if a non-default
283: // discriminator value is specified
284: for (int i = 0; i < typeCode.member_count(); i++) {
285: if (type().member_label(i).equal(discriminator)) {
286: select_member();
287: break;
288: }
289: }
290: } else {
291: // non-default member, check if the member has changed
292: if (!type().member_label(memberIndex).equal(
293: discriminator)) {
294: select_member();
295: }
296: }
297: } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
298: throw unexpectedException(e);
299: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
300: throw unexpectedException(e);
301: }
302:
303: // set the current position to zero if there is no active member
304: if (has_no_active_member()) {
305: pos = 0;
306: }
307: }
308:
309: /**
310: * updates the private instance variables member, member_name and
311: * member_index according to the current discriminator value
312: */
313:
314: private void select_member() {
315: member = null;
316: try {
317: /* search through all members and compare their label with
318: the discriminator */
319: for (int i = 0; i < type().member_count(); i++) {
320: if (type().member_label(i).equal(discriminator)) {
321: try {
322: member = dynFactory
323: .create_dyn_any_from_type_code(type()
324: .member_type(i));
325: } catch (InconsistentTypeCode e) {
326: throw unexpectedException(e);
327: }
328: memberName = type().member_name(i);
329: memberIndex = i;
330: break;
331: }
332: }
333:
334: /* none found, use default, if there is one */
335:
336: if (member == null) {
337: int def_idx = type().default_index();
338: if (def_idx != -1) {
339: try {
340: member = dynFactory
341: .create_dyn_any_from_type_code(type()
342: .member_type(def_idx));
343: } catch (InconsistentTypeCode e) {
344: throw unexpectedException(e);
345: }
346: memberName = type().member_name(def_idx);
347: memberIndex = def_idx;
348: }
349: }
350: } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
351: throw unexpectedException(e);
352: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
353: throw unexpectedException(e);
354: }
355: }
356:
357: /**
358: * sets the discriminator to a value that is consistent with the
359: * value of the default case of a union; it sets the current
360: * position to zero and causes component_count to return 2.
361: *
362: * @throws TypeMismatch if the union does not have an explicit
363: * default case.
364: */
365:
366: public void set_to_default_member() throws TypeMismatch {
367: checkDestroyed();
368: try {
369: int def_idx = type().default_index();
370: if (def_idx == -1) {
371: throw new TypeMismatch();
372: }
373: pos = 0;
374:
375: // do nothing if the discriminator is already set to a default value
376: if (memberIndex != def_idx) {
377: try {
378: set_to_unlisted_label();
379: } catch (TypeMismatch e) {
380: throw unexpectedException(e);
381: }
382: select_member();
383: }
384: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
385: throw unexpectedException(e);
386: }
387: }
388:
389: /**
390: * sets the discriminator to a value that does not correspond to
391: * any of the union's case labels; it sets the current position
392: * to zero and causes component_count to return 1.
393: *
394: * @throws TypeMismatch if the union has an explicit default
395: * case or uses the entire range of discriminator values for
396: * explicit case labels.
397: */
398:
399: public void set_to_no_active_member() throws TypeMismatch {
400: checkDestroyed();
401: try {
402: /* if there is a default index, we do have active members */
403: if (type().default_index() != -1) {
404: throw new TypeMismatch();
405: }
406: pos = 0;
407:
408: // do nothing if discriminator is already set to no active member
409: if (!has_no_active_member()) {
410: set_to_unlisted_label();
411: }
412: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
413: throw unexpectedException(e);
414: }
415: }
416:
417: /* find a discriminator value that is not an explicit case label */
418: private void set_to_unlisted_label() throws TypeMismatch {
419: try {
420: switch (type().discriminator_type().kind().value()) {
421: case TCKind._tk_boolean: {
422: boolean found;
423: boolean cur_bool;
424: org.omg.CORBA.Any check_val = null;
425:
426: for (int i = 0; i < 2; i++) {
427: if (i == 0) {
428: cur_bool = true;
429: } else {
430: cur_bool = false;
431: }
432: check_val = orb.create_any();
433: check_val.insert_boolean(cur_bool);
434:
435: found = false; // is the value used as a label?
436: for (int j = 0; j < type().member_count() && !found; j++) {
437: if (check_val.equal(type().member_label(j))) {
438: found = true;
439: }
440: }
441:
442: if (!found) {
443: // the value is not found among the union's label
444: discriminator = check_val;
445: return;
446: }
447: }
448: // no unused value found
449: throw new TypeMismatch();
450: }
451: case TCKind._tk_char: {
452: // assume there is a printable char not used as a label!
453: boolean found;
454: org.omg.CORBA.Any check_val = null;
455:
456: // 33 to 126 defines a reasonable set of printable chars
457: for (int i = 0; i < 127; i++) {
458: check_val = orb.create_any();
459: check_val.insert_char((char) i);
460:
461: found = false; // is the value used as a label?
462: for (int j = 0; j < type().member_count() && !found; j++) {
463: if (check_val.equal(type().member_label(j))) {
464: found = true;
465: }
466: }
467:
468: if (!found) {
469: // the value is not found among the union's label
470: discriminator = check_val;
471: return;
472: }
473: }
474: // no unused value found, should not happen
475: throw new TypeMismatch();
476: }
477: case TCKind._tk_short: {
478: // assume there is an unsigned short not used as a label!
479: boolean found;
480: org.omg.CORBA.Any check_val = null;
481:
482: short max_short = 32767;
483: for (short i = 0; i < max_short; i++) {
484: check_val = orb.create_any();
485: check_val.insert_short(i);
486:
487: found = false; // is the value used as a label?
488: for (int j = 0; j < type().member_count() && !found; j++) {
489: if (check_val.equal(type().member_label(j))) {
490: found = true;
491: }
492: }
493:
494: if (!found) {
495: // the value is not found among the union's label
496: discriminator = check_val;
497: return;
498: }
499: }
500: // no unused value found, should not happen
501: throw new TypeMismatch();
502: }
503: case TCKind._tk_long: {
504: // assume there is an unsigned int not used as a label!
505: boolean found;
506: org.omg.CORBA.Any check_val = null;
507:
508: int max_int = 2147483647;
509: for (int i = 0; i < max_int; i++) {
510: check_val = orb.create_any();
511: check_val.insert_long(i);
512:
513: found = false; // is the value used as a label?
514: for (int j = 0; j < type().member_count() && !found; j++) {
515: if (check_val.equal(type().member_label(j))) {
516: found = true;
517: }
518: }
519:
520: if (!found) {
521: // the value is not found among the union's label
522: discriminator = check_val;
523: return;
524: }
525: }
526: // no unused value found, should not happen
527: throw new TypeMismatch();
528: }
529: case TCKind._tk_longlong: {
530: // assume there is an unsigned long not used as a label!
531: boolean found;
532: org.omg.CORBA.Any check_val = null;
533:
534: long max_long = 2147483647; // this should be sufficient!
535: for (long i = 0; i < max_long; i++) {
536: check_val = orb.create_any();
537: check_val.insert_longlong(i);
538:
539: found = false; // is the value used as a label?
540: for (int j = 0; j < type().member_count() && !found; j++) {
541: if (check_val.equal(type().member_label(j))) {
542: found = true;
543: }
544: }
545:
546: if (!found) {
547: // the value is not found among the union's label
548: discriminator = check_val;
549: return;
550: }
551: }
552: // no unused value found, should not happen
553: throw new TypeMismatch();
554: }
555: case TCKind._tk_enum: {
556: org.omg.DynamicAny.DynEnum dynEnum = null;
557: try {
558: dynEnum = (org.omg.DynamicAny.DynEnum) dynFactory
559: .create_dyn_any_from_type_code(discriminator
560: .type());
561: } catch (InconsistentTypeCode e) {
562: throw unexpectedException(e);
563: }
564:
565: boolean found;
566: for (int i = 0; i < discriminator.type().member_count(); i++) {
567: try {
568: dynEnum.set_as_string(discriminator.type()
569: .member_name(i));
570: } catch (InvalidValue e) {
571: throw unexpectedException(e);
572: }
573:
574: found = false; // is the value used as a label?
575: for (int j = 0; j < type().member_count() && !found; j++) {
576: if (dynEnum.to_any().equal(
577: type().member_label(j))) {
578: found = true;
579: }
580: }
581:
582: if (!found) {
583: // the enum value is not found among the union's label
584: discriminator = dynEnum.to_any();
585: return;
586: }
587: }
588: // no unused value found
589: throw new TypeMismatch();
590: }
591: default:
592: throw new TypeMismatch();
593: }
594: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
595: throw unexpectedException(e);
596: } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
597: throw unexpectedException(e);
598: }
599: }
600:
601: /**
602: * @return true, if the union has no active member (that is, the
603: * union's value consists solely of its discriminator because
604: * the discriminator has a value that is not listed as an explicit
605: * case label). Calling this operation on a union that has a
606: * default case returns false. Calling this operation on a union
607: * that uses the entire range of discriminator values for explicit
608: * case labels returns false.
609: */
610:
611: public boolean has_no_active_member() {
612: checkDestroyed();
613: try {
614: if (type().default_index() != -1) {
615: return false;
616: }
617:
618: for (int i = 0; i < typeCode.member_count(); i++) {
619: if (discriminator.equal(typeCode.member_label(i))) {
620: return false;
621: }
622: }
623: return true;
624: } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
625: throw unexpectedException(e);
626: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
627: throw unexpectedException(e);
628: }
629: }
630:
631: /**
632: * @return the TCKind value of the discriminator's TypeCode.
633: */
634:
635: public org.omg.CORBA.TCKind discriminator_kind() {
636: checkDestroyed();
637: return discriminator.type().kind();
638: }
639:
640: /**
641: * @return the currently active member.
642: * @throws InvalidValue if the union has no active member
643: */
644:
645: public org.omg.DynamicAny.DynAny member() throws InvalidValue {
646: checkDestroyed();
647: if (has_no_active_member()) {
648: throw new InvalidValue();
649: }
650:
651: return member;
652: }
653:
654: /**
655: * @return the TypeCode kind of the currently active member.
656: * @throws InvalidValue if the union has no active member
657: */
658:
659: public org.omg.CORBA.TCKind member_kind() throws InvalidValue {
660: checkDestroyed();
661: if (has_no_active_member()) {
662: throw new InvalidValue();
663: }
664:
665: return member.type().kind();
666: }
667:
668: /**
669: * @return the name of the currently active member.
670: * @throws InvalidValue if the union has no active member
671: */
672:
673: public String member_name() throws InvalidValue {
674: checkDestroyed();
675: if (has_no_active_member()) {
676: throw new InvalidValue();
677: }
678: return memberName;
679: }
680:
681: public void destroy() {
682: super .destroy();
683: discriminator = null;
684: member = null;
685: memberName = null;
686: memberIndex = -1;
687: }
688:
689: /* iteration interface */
690:
691: public org.omg.DynamicAny.DynAny current_component() {
692: checkDestroyed();
693: if (pos == -1) {
694: return null;
695: }
696:
697: if (pos == 0) {
698: return get_discriminator();
699: }
700:
701: try {
702: return member();
703: } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue e) {
704: throw unexpectedException(e);
705: }
706: }
707: }
|