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