Source for gnu.java.beans.encoder.ArrayPersistenceDelegate

   1: /* ArrayPersistenceDelegate.java - A PersistenceDelegate that handles arrays.
   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.java.beans.encoder;
  40: 
  41: import java.beans.Encoder;
  42: import java.beans.Expression;
  43: import java.beans.PersistenceDelegate;
  44: import java.beans.Statement;
  45: 
  46: import java.lang.reflect.Array;
  47: import java.util.HashMap;
  48: 
  49: public class ArrayPersistenceDelegate extends PersistenceDelegate
  50: {
  51:   private static final HashMap NULL_VALUES = new HashMap();
  52: 
  53:   static
  54:     {
  55:       NULL_VALUES.put(Boolean.TYPE, Boolean.FALSE);
  56:       NULL_VALUES.put(Byte.TYPE, Byte.valueOf((byte) 0));
  57:       NULL_VALUES.put(Short.TYPE, Short.valueOf((short) 0));
  58:       NULL_VALUES.put(Integer.TYPE, Integer.valueOf(0));
  59:       NULL_VALUES.put(Long.TYPE, Long.valueOf(0));
  60:       NULL_VALUES.put(Float.TYPE, Float.valueOf(0.0f));
  61:       NULL_VALUES.put(Double.TYPE, Double.valueOf(0.0));
  62:     }
  63: 
  64:   protected Expression instantiate(Object oldInstance, Encoder out)
  65:   {
  66:     Class type = oldInstance.getClass().getComponentType();
  67: 
  68:     // oldInstance is expected to be an array, then
  69:     // getClass().getComponentType() should lead
  70:     // to its component type.
  71:     assert (type != null);
  72: 
  73:     // Not handling primitive types in a special way here
  74:     // causes that Class.forName("int") is built as an Expression
  75:     // later which would cause an exception if executed. A special
  76:     // handling to avoid the execution for primitive types can be
  77:     // java.beans.Encoder.writeExpression() .
  78:     return new Expression(
  79:                           oldInstance,
  80:                           Array.class,
  81:                           "newInstance",
  82:                           new Object[] {
  83:                             type,
  84:                             new Integer(Array.getLength(oldInstance)) });
  85:   }
  86: 
  87:   protected void initialize(Class type, Object oldInstance, Object newInstance,
  88:                             Encoder out)
  89:   {
  90:     int length = Array.getLength(oldInstance);
  91: 
  92:     // Compares the array value against a prototypical
  93:     // null value of the array's component type in order to skip
  94:     // writing the default values of an array.
  95: 
  96:     // Note: I have no idea why the persistence delegate for arrays writes
  97:     // an Expression that reads the value and then writes a Statement that sets
  98:     // the value. However it turned out that object arrays work better with the
  99:     // get-Expression and primitive array work fine with the set-Statement.
 100: 
 101:     type = type.getComponentType();
 102:     if (type.isPrimitive())
 103:       {
 104:         Object nullValue = NULL_VALUES.get(type);
 105: 
 106:         for (int i = 0; i < length; i++)
 107:           {
 108:             Object oldValue = Array.get(oldInstance, i);
 109: 
 110:             if (!oldValue.equals(nullValue))
 111:               {
 112:                 out.writeExpression(new Expression(Array.class, "get",
 113:                                                    new Object[] { oldInstance,
 114:                                                                  Integer.valueOf(i),
 115:                                                                  }));
 116: 
 117:                 out.writeStatement(new Statement(Array.class, "set",
 118:                                                new Object[] {
 119:                                                  oldInstance,
 120:                                                  Integer.valueOf(i),
 121:                                                  oldValue
 122:                                                  }));
 123:               }
 124:           }
 125: 
 126:       }
 127:     else
 128:       {
 129: 
 130:         for (int i = 0; i < length; i++)
 131:           {
 132:             Object oldValue = Array.get(oldInstance, i);
 133: 
 134:             if (oldValue != null)
 135:               {
 136:                 out.writeExpression(new Expression(Array.class, "get",
 137:                                                  new Object[] { oldInstance,
 138:                                                                Integer.valueOf(i),
 139:                                                                }));
 140: 
 141:                 out.writeStatement(new Statement(Array.class, "set",
 142:                                                    new Object[] {
 143:                                                      oldInstance,
 144:                                                      Integer.valueOf(i),
 145:                                                      oldValue
 146:                                                      }));
 147:               }
 148:           }
 149:       }
 150: 
 151:   }
 152: 
 153: }