Source for gnu.CORBA.DynAn.gnuDynArray

   1: /* gnuDynArray.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: import gnu.CORBA.HolderLocator;
  43: 
  44: import org.omg.CORBA.Any;
  45: import org.omg.CORBA.BAD_PARAM;
  46: import org.omg.CORBA.ORB;
  47: import org.omg.CORBA.TCKind;
  48: import org.omg.CORBA.TypeCode;
  49: import org.omg.CORBA.TypeCodePackage.BadKind;
  50: import org.omg.CORBA.portable.Streamable;
  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.DynArray;
  56: 
  57: import java.io.Serializable;
  58: 
  59: import java.lang.reflect.Array;
  60: import java.lang.reflect.Field;
  61: 
  62: /**
  63:  * Provides support for dynamic array or sequence, where all members have the
  64:  * same final_type.
  65:  *
  66:  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
  67:  */
  68: public class gnuDynArray
  69:   extends DivideableAny
  70:   implements DynArray, Serializable
  71: {
  72:   /**
  73:    * Use serialVersionUID for interoperability.
  74:    */
  75:   private static final long serialVersionUID = 1;
  76: 
  77:   /**
  78:    * The component "official" type (may be alias).
  79:    */
  80:   final TypeCode official_components;
  81: 
  82:   /**
  83:    * The component "final" type, after resolving any aliases.
  84:    */
  85:   final TypeCode final_components;
  86: 
  87:   /**
  88:    * Creates new array.
  89:    *
  90:    * @param aType the final_type of array.
  91:    * @param aFactory the factory, used to initialise default values.
  92:    * @param orb the ORB to that this DynAny belongs.
  93:    * @param initialise_array if false, the array is not initialised in
  94:    * constructor.
  95:    *
  96:    *
  97:    * @throws BAD_PARAM if the passed typecode does not provide the length().
  98:    */
  99:   public gnuDynArray(TypeCode oType, TypeCode aType, gnuDynAnyFactory aFactory,
 100:                      ORB anOrb, boolean initialise_array
 101:                     )
 102:               throws BAD_PARAM
 103:   {
 104:     super(oType, aType, aFactory, anOrb);
 105: 
 106:     try
 107:       {
 108:         official_components = final_type.content_type();
 109: 
 110:         TypeCode component = official_components;
 111:         while (component.kind().value() == TCKind._tk_alias)
 112:           component = component.content_type();
 113:         final_components = component;
 114: 
 115:         if (initialise_array)
 116:           {
 117:             array = new DynAny[ aType.length() ];
 118:             for (int i = 0; i < array.length; i++)
 119:               {
 120:                 array [ i ] =
 121:                   factory.create_dyn_any_from_type_code(official_components);
 122:               }
 123:           }
 124:       }
 125:     catch (Exception e)
 126:       {
 127:         BAD_PARAM bad = new BAD_PARAM("Unable to initialise array");
 128:         bad.initCause(e);
 129:         throw bad;
 130:       }
 131:   }
 132: 
 133:   /**
 134:    * Copy one DynAny into another.
 135:    */
 136:   public void assign(DynAny from)
 137:               throws TypeMismatch
 138:   {
 139:     checkType(official_type, from.type());
 140:     if (from instanceof DynArray && from.component_count() == array.length)
 141:       {
 142:         DynArray dyn = (DynArray) from;
 143:         array = dyn.get_elements_as_dyn_any();
 144:       }
 145:     else
 146:       throw new TypeMismatch();
 147:   }
 148: 
 149:   /**
 150:    * Create a copy.
 151:    */
 152:   public DynAny copy()
 153:   {
 154:     DynAny[] c = new DynAny[ array.length ];
 155:     for (int i = 0; i < c.length; i++)
 156:       {
 157:         c [ i ] = array [ i ].copy();
 158:       }
 159: 
 160:     gnuDynArray d =
 161:       new gnuDynArray(official_type, final_type, factory, orb, false);
 162:     d.array = c;
 163:     return d;
 164:   }
 165: 
 166:   /**
 167:    * Get elements as array of anys.
 168:    */
 169:   public Any[] get_elements()
 170:   {
 171:     Any[] r = new Any[ array.length ];
 172:     for (int i = 0; i < r.length; i++)
 173:       r [ i ] = array [ i ].to_any();
 174:     return r;
 175:   }
 176: 
 177:   /** {@inheritDoc} */
 178:   public DynAny[] get_elements_as_dyn_any()
 179:   {
 180:     DynAny[] a = new DynAny[ array.length ];
 181:     for (int i = 0; i < a.length; i++)
 182:       {
 183:         a [ i ] = array [ i ].copy();
 184:       }
 185:     return a;
 186:   }
 187: 
 188:   /**
 189:    * Set elements when array of dyn anys is provided. This method can set nested
 190:    * data structures as an array components.
 191:    */
 192:   public void set_elements_as_dyn_any(DynAny[] value)
 193:                                throws InvalidValue, TypeMismatch
 194:   {
 195:     if (value.length != array.length)
 196:       throw new InvalidValue(sizeMismatch(array.length, value.length));
 197:     for (int i = 0; i < value.length; i++)
 198:       {
 199:         checkType(official_components, value [ i ].type());
 200:         array [ i ].assign(value [ i ]);
 201:       }
 202:     pos = 0;
 203:     valueChanged();
 204:   }
 205: 
 206:   /**
 207:    * Set elements when array of ordinary anys is provided.
 208:    */
 209:   public void set_elements(Any[] value)
 210:                     throws InvalidValue, TypeMismatch
 211:   {
 212:     if (value.length != array.length)
 213:       throw new InvalidValue(sizeMismatch(array.length, value.length));
 214: 
 215:     for (int i = 0; i < value.length; i++)
 216:       {
 217:         checkType(official_components, value [ i ].type());
 218:         try
 219:           {
 220:             array [ i ] = factory.create_dyn_any(value [ i ]);
 221:           }
 222:         catch (InconsistentTypeCode e)
 223:           {
 224:             TypeMismatch t = new TypeMismatch();
 225:             t.initCause(e);
 226:             throw t;
 227:           }
 228:       }
 229:     pos = 0;
 230:     valueChanged();
 231:   }
 232: 
 233:   /**
 234:    * Done via reflection.
 235:    */
 236:   public Any to_any()
 237:   {
 238:     try
 239:       {
 240:         Streamable memberHolder =
 241:           HolderLocator.createHolder(official_components);
 242: 
 243:         if (memberHolder == null)
 244:           memberHolder = HolderLocator.createHolder(final_components);
 245: 
 246:         Class memberHolderClass = memberHolder.getClass();
 247:         Class memberClass = memberHolderClass.getField("value").getType();
 248: 
 249:         Object members = Array.newInstance(memberClass, array.length);
 250:         Object member;
 251:         Any am;
 252:         Field value = memberHolder.getClass().getField("value");
 253: 
 254:         for (int i = 0; i < array.length; i++)
 255:           {
 256:             // Recursive call should support multidimensional arrays.
 257:             am = array [ i ].to_any();
 258:             memberHolder = am.extract_Streamable();
 259:             member = value.get(memberHolder);
 260:             Array.set(members, i, member);
 261:           }
 262: 
 263:         Streamable arrayHolder = HolderLocator.createHolder(official_type);
 264:         arrayHolder.getClass().getField("value").set(arrayHolder, members);
 265: 
 266:         Any g = createAny();
 267:         g.insert_Streamable(arrayHolder);
 268:         g.type(official_type);
 269:         return g;
 270:       }
 271:     catch (Exception e)
 272:       {
 273:         throw new Unexpected(e);
 274:       }
 275:   }
 276: 
 277:   /**
 278:    * Done via reflection.
 279:    */
 280:   public void from_any(Any an_any)
 281:                 throws TypeMismatch, InvalidValue
 282:   {
 283:     checkType(official_type, an_any.type());
 284:     try
 285:       {
 286:         Streamable s = an_any.extract_Streamable();
 287:         Object members = s.getClass().getField("value").get(s);
 288: 
 289:         checkArrayValid(members);
 290: 
 291:         Any member;
 292:         Streamable holder;
 293:         Class holderClass = null;
 294: 
 295:         for (int i = 0; i < array.length; i++)
 296:           {
 297:             if (holderClass == null)
 298:               {
 299:                 holder = HolderLocator.createHolder(official_components);
 300:                 if (holder == null)
 301:                   holder = HolderLocator.createHolder(final_components);
 302:                 holderClass = holder.getClass();
 303:               }
 304:             else
 305:               holder = (Streamable) holderClass.newInstance();
 306: 
 307:             member = createAny();
 308:             holder.getClass().getField("value").set(holder,
 309:                                                     Array.get(members, i)
 310:                                                    );
 311:             member.insert_Streamable(holder);
 312:             member.type(official_components);
 313: 
 314:             // This may lead to recursion, supporting multidimensional
 315:             // arrays.
 316:             array [ i ].from_any(member);
 317:           }
 318:       }
 319:     catch (Exception ex)
 320:       {
 321:         TypeMismatch t = new TypeMismatch();
 322:         t.initCause(ex);
 323:         throw t;
 324:       }
 325:     valueChanged();
 326:   }
 327: 
 328:   /**
 329:    * Check if array size is valid and (for sequences) resized
 330:    * if required. Called from from_any.
 331:    */
 332:   protected void checkArrayValid(Object members)
 333:                           throws TypeMismatch, InvalidValue
 334:   {
 335:     if (array.length != Array.getLength(members))
 336:       throw new InvalidValue(sizeMismatch(array.length, Array.getLength(members)));
 337:   }