Source for gnu.CORBA.DynAn.gnuDynUnion

   1: /* gnuDynUnion.java --
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.CORBA.DynAn;
  40: 
  41: import gnu.CORBA.Unexpected;
  42: 
  43: import org.omg.CORBA.Any;
  44: import org.omg.CORBA.MARSHAL;
  45: import org.omg.CORBA.ORB;
  46: import org.omg.CORBA.TCKind;
  47: import org.omg.CORBA.TypeCode;
  48: import org.omg.CORBA.TypeCodePackage.BadKind;
  49: import org.omg.CORBA.portable.InputStream;
  50: import org.omg.CORBA.portable.OutputStream;
  51: import org.omg.DynamicAny.DynAny;
  52: import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode;
  53: import org.omg.DynamicAny.DynAnyPackage.InvalidValue;
  54: import org.omg.DynamicAny.DynAnyPackage.TypeMismatch;
  55: import org.omg.DynamicAny.DynUnion;
  56: 
  57: import java.io.Serializable;
  58: 
  59: /**
  60:  * Implementation of DynUnion.
  61:  *
  62:  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
  63:  */
  64: public class gnuDynUnion
  65:   extends DivideableAny
  66:   implements DynUnion, Serializable, ValueChangeListener
  67: {
  68:   /**
  69:    * Use serialVersionUID for interoperability.
  70:    */
  71:   private static final long serialVersionUID = 1;
  72: 
  73:   /**
  74:    * The discrimintor of this union.
  75:    */
  76:   DynAny discriminator;
  77: 
  78:   /**
  79:    * The message string that occurs several times throwing exception.
  80:    */
  81:   static String NOAM = "No active member";
  82: 
  83:   /**
  84:    * Create a new instance with the given typecode.
  85:    *
  86:    * @param aType the final_type, must be final_type of the union.
  87:    */
  88:   public gnuDynUnion(TypeCode oType, TypeCode aType, gnuDynAnyFactory aFactory,
  89:                      ORB anOrb
  90:                     )
  91:               throws InconsistentTypeCode
  92:   {
  93:     super(oType, aType, aFactory, anOrb);
  94:     try
  95:       {
  96:         discriminator =
  97:           factory.create_dyn_any_from_type_code(final_type.discriminator_type());
  98: 
  99:         ((AbstractAny) discriminator).listener = this;
 100: 
 101:         if (final_type.default_index() >= 0)
 102:           set_to_default_member();
 103:         else
 104:           set_to_no_active_member();
 105:       }
 106:     catch (Exception ex)
 107:       {
 108:         InconsistentTypeCode inc = new InconsistentTypeCode("discriminator");
 109:         inc.initCause(ex);
 110:         throw inc;
 111:       }
 112:   }
 113: 
 114:   /*
 115:    * (non-Javadoc)
 116:    *
 117:    * @see gnu.CORBA.DynAn.DivideableAny#to_any()
 118:    */
 119:   public Any to_any()
 120:   {
 121:     Any a = createAny();
 122:     OutputStream ou = a.create_output_stream();
 123:     discriminator.to_any().write_value(ou);
 124:     if (array.length == 2)
 125:       array [ 1 ].to_any().write_value(ou);
 126:     a.read_value(ou.create_input_stream(), final_type);
 127:     return a;
 128:   }
 129: 
 130:   /**
 131:    * Assign from another identical structure.
 132:    */
 133:   public void assign(DynAny from)
 134:               throws TypeMismatch
 135:   {
 136:     checkType(official_type, from.type());
 137:     if (!(from instanceof DynUnion))
 138:       throw new TypeMismatch("DynUnion required");
 139:     else
 140:       {
 141:         try
 142:           {
 143:             DynUnion u = (DynUnion) from;
 144:             discriminator.assign(u.get_discriminator());
 145:             if (u.has_no_active_member())
 146:               {
 147:                 if (array.length != 1)
 148:                   array = new DynAny[] { discriminator };
 149:               }
 150:             else
 151:               {
 152:                 if (array.length != 2)
 153:                   array = new DynAny[] { discriminator, u.member().copy() };
 154:                 else
 155:                   array [ 1 ] = u.member().copy();
 156:               }
 157:           }
 158:         catch (InvalidValue e)
 159:           {
 160:             throw new Unexpected(e);
 161:           }
 162:       }
 163:     valueChanged();
 164:   }
 165: 
 166:   /** @inheritDoc */
 167:   public DynAny copy()
 168:   {
 169:     try
 170:       {
 171:         gnuDynUnion other =
 172:           new gnuDynUnion(official_type, final_type, factory, orb);
 173:         other.discriminator = discriminator.copy();
 174:         ((AbstractAny) other.discriminator).listener = other;
 175:         if (array.length == 1)
 176:           {
 177:             other.array = new DynAny[] { other.discriminator };
 178:           }
 179:         else
 180:           {
 181:             other.array =
 182:               new DynAny[] { other.discriminator, array [ 1 ].copy() };
 183:           }
 184:         return other;
 185:       }
 186:     catch (InconsistentTypeCode ex)
 187:       {
 188:         throw new Unexpected(ex);
 189:       }
 190:   }
 191: 
 192:   /**
 193:    * Done via reading from stream.
 194:    */
 195:   public void from_any(Any an_any)
 196:                 throws TypeMismatch, InvalidValue
 197:   {
 198:     checkType(official_type, an_any.type());
 199: 
 200:     Any adis = createAny();
 201:     try
 202:       {
 203:         InputStream stream = an_any.create_input_stream();
 204:         adis.read_value(stream, final_type.discriminator_type());
 205: 
 206:         DynAny nd = factory.create_dyn_any(adis);
 207: 
 208:         set_discriminator(nd);
 209:         if (array.length == 2)
 210:           {
 211:             // Reusing the same Any <code>adis</code>.
 212:             adis.read_value(stream, array [ 1 ].type());
 213:             array [ 1 ].from_any(adis);
 214:           }
 215:       }
 216:     catch (InconsistentTypeCode it)
 217:       {
 218:         TypeMismatch t = new TypeMismatch();
 219:         t.initCause(it);
 220:         throw t;
 221:       }
 222:     catch (MARSHAL m)
 223:       {
 224:         InvalidValue t = new InvalidValue();
 225:         t.initCause(m);
 226:         throw t;
 227:       }
 228:     catch (BadKind b)
 229:       {
 230:         throw new Unexpected(b);
 231:       }
 232:     valueChanged();
 233:   }
 234: 
 235:   /** @inheritDoc */
 236:   public TCKind discriminator_kind()
 237:   {
 238:     return discriminator.type().kind();
 239:   }
 240: 
 241:   /** @inheritDoc */
 242:   public DynAny get_discriminator()
 243:   {
 244:     return discriminator;
 245:   }
 246: 
 247:   /** @inheritDoc */
 248:   public boolean has_no_active_member()
 249:   {
 250:     return array.length == 1;
 251:   }
 252: 
 253:   /** @inheritDoc */
 254:   public TCKind member_kind()
 255:                      throws InvalidValue
 256:   {
 257:     return member().type().kind();
 258:   }
 259: 
 260:   /**
 261:    * Get the name of the current variant of the union.
 262:    */
 263:   public String member_name()
 264:                      throws InvalidValue
 265:   {
 266:     if (array.length == 1)
 267:       throw new InvalidValue(NOAM);
 268:     try
 269:       {
 270:         Any da = discriminator.to_any();
 271: 
 272: 
 273:         // Get the discriminator variant.
 274:         for (int i = 0; i < final_type.member_count(); i++)
 275:           {
 276:             if (final_type.member_label(i).equal(da))
 277:               return final_type.member_name(i);
 278:           }
 279:         throw new InvalidValue(NOAM);
 280:       }
 281:     catch (Exception e)
 282:       {
 283:         InvalidValue t = new InvalidValue("Err");
 284:         t.initCause(e);
 285:         throw t;
 286:       }
 287:   }
 288: 
 289:   /** @inheritDoc */
 290:   public DynAny member()
 291:                 throws InvalidValue
 292:   {
 293:     if (array.length < 2)
 294:       throw new InvalidValue(NOAM);
 295:     else
 296:       return array [ 1 ];
 297:   }
 298: 
 299:   /**
 300:    * Set the union discriminator.
 301:    */
 302:   public void set_discriminator(DynAny aDiscriminator)
 303:                          throws TypeMismatch
 304:   {
 305:     try
 306:       {
 307:         if (!aDiscriminator.type().equal(final_type.discriminator_type()))
 308:           throw new TypeMismatch("Wrong discriminator final_type for " +
 309:                                  final_type.name()
 310:                                 );
 311: 
 312:         // Seting the same discriminator value again should not change
 313:         // the fields of the current member.
 314:         if (!discriminator.equal(aDiscriminator))
 315:           {
 316:             discriminator.assign(aDiscriminator);
 317:             updateMember();
 318:           }
 319:         else
 320:           {
 321:             pos = array.length == 2 ? 1 : 0;
 322:           }
 323:       }
 324:     catch (Exception e)
 325:       {
 326:         TypeMismatch t = new TypeMismatch();
 327:         t.initCause(e);
 328:         throw t;
 329:       }
 330:   }
 331: 
 332:   /**
 333:    * Set to default member, if one exists.
 334:    */
 335:   public void set_to_default_member()
 336:                              throws TypeMismatch
 337:   {
 338:     try
 339:       {
 340:         int di = final_type.default_index();
 341:         if (di < 0)
 342:           throw new TypeMismatch("Union " + final_type.name() +
 343:                                  "has no default index"
 344:                                 );
 345: 
 346:         Any da = final_type.member_label(di);
 347:         discriminator.from_any(da);
 348:         updateMember();
 349:       }
 350:     catch (TypeMismatch m)
 351:       {
 352:         // This one OK.
 353:         throw m;
 354:       }
 355:     catch (Exception e)
 356:       {
 357:         TypeMismatch t = new TypeMismatch();
 358:         t.initCause(e);
 359:         throw t;
 360:       }
 361:   }
 362: 
 363:   /** @inheritDoc */
 364:   public void set_to_no_active_member()
 365:                                throws TypeMismatch
 366:   {
 367:     try
 368:       {
 369:         if (final_type.default_index() >= 0)
 370:           {
 371:             throw new TypeMismatch("Explicit default case defined.");
 372:           }
 373:       }
 374:     catch (BadKind ex)
 375:       {
 376:         // The default index is not set.
 377:       }
 378:     array = new DynAny[] { discriminator };
 379:     valueChanged();
 380:   }
 381: 
 382:   /**
 383:    * Update member, in accordance with discriminator value.
 384:    */
 385:   public void updateMember()
 386:                     throws TypeMismatch
 387:   {
 388:     try
 389:       {
 390:         Any da = discriminator.to_any();
 391: 
 392: 
 393:         // Get the discriminator variant.
 394:         for (int i = 0; i < final_type.member_count(); i++)
 395:           {
 396:             if (final_type.member_label(i).equal(da))
 397:               {
 398:                 array =
 399:                   new DynAny[]
 400:                   {
 401:                     discriminator,
 402:                     factory.create_dyn_any_from_type_code(final_type.member_type(i))
 403:                   };
 404:                 pos = 1;
 405:                 valueChanged();
 406:                 return;
 407:               }
 408:           }
 409:       }
 410:     catch (Exception e)
 411:       {
 412:         TypeMismatch t = new TypeMismatch();
 413:         t.initCause(e);
 414:         throw t;
 415:       }
 416: 
 417:     // Discrimintator does not point to valid member.
 418:     array = new DynAny[] { discriminator };
 419:     pos = 0;
 420:     valueChanged();
 421:   }
 422: 
 423:   /**
 424:    * Called when the discriminator is changed.
 425:    */
 426:   public void changed()
 427:   {
 428:     try
 429:       {
 430:         updateMember();
 431:       }
 432:     catch (TypeMismatch ex)
 433:       {
 434:         throw new Unexpected(ex);
 435:       }
 436:   }
 437: }