/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

package org.apache.yoko.rmi.impl;

import java.io.Externalizable;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.rmi.Remote;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ValueMember;
import org.omg.CORBA.portable.IndirectionException;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.OutputStream;

abstract class ArrayDescriptor extends ValueDescriptor {
    final Class elementType;
    final Class basicType;
    private final int order;

    protected ArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, rep);
        logger.fine("Creating an array descriptor for type " + type.getName() + " holding elements of " + elemType.getName());
        this.elementType = elemType;

        int order = 1;
        Class basicType = elemType;
        while (basicType.isArray()) {
            basicType = basicType.getComponentType();
            order++;
        }
        this.basicType = basicType;
        this.order = order;
    }

    @Override
    protected String genRepId() {
        if (elementType.isPrimitive() || elementType == Object.class)
            return String.format("RMI:%s:%016X", type.getName(), 0);

        TypeDescriptor desc = repo.getDescriptor(elementType);
        String elemRep = desc.getRepositoryID();
        String hash = elemRep.substring(elemRep.indexOf(':', 4));
        return String.format("RMI:%s:%s", type.getName(), hash);
    }

    // repository ID for the contained elements
    private volatile String _elementRepid = null;
    private final String genElemRepId() {
        if (elementType.isPrimitive() || elementType == Object.class) {
            // use the descriptor type past the array type marker
            return String.format("RMI:%s:%016X", type.getName().substring(1), 0);
        }
        return repo.getDescriptor(elementType).getRepositoryID();
    }

    public String getElementRepositoryID() {
        if (_elementRepid == null) _elementRepid = genElemRepId();
        return _elementRepid;
    }

    @Override
    protected final String genIDLName() {
        StringBuffer sb = new StringBuffer("org_omg_boxedRMI_");

        TypeDescriptor desc = repo.getDescriptor(basicType);
        
        // The logic that looks for the last "_" fails when this is a 
        // long_long primitive type.  The primitive types have a "" package 
        // name, so check those first.  If it's not one of the primitives, 
        // then we can safely split using the last index position.
        String pkgName = desc.getPackageName(); 
        if (pkgName.length() == 0) {
            sb.append("seq");
            sb.append(order);
            sb.append('_');
            sb.append(desc.getTypeName());
        }
        else {
            String elemName = desc.getIDLName();

            int idx = elemName.lastIndexOf('_');

            pkgName = elemName.substring(0, idx + 1);
            String elmName = elemName.substring(idx + 1);

            sb.append(pkgName);

            sb.append("seq");
            sb.append(order);
            sb.append('_');

            sb.append(elmName);
        }

        return sb.toString();
    }

    static ArrayDescriptor get(final Class type, TypeRepository rep) {
        logger.fine("retrieving an array descriptor for class " + type.getName());
        if (!type.isArray()) {
            throw new IllegalArgumentException("type is not an array");
        }

        Class elemType = type.getComponentType();

        if (elemType.isPrimitive()) {
            if (elemType == Boolean.TYPE) {
                return new BooleanArrayDescriptor(type, elemType, rep);
            } else if (elemType == Byte.TYPE) {
                return new ByteArrayDescriptor(type, elemType, rep);
            } else if (elemType == Character.TYPE) {
                return new CharArrayDescriptor(type, elemType, rep);
            } else if (elemType == Short.TYPE) {
                return new ShortArrayDescriptor(type, elemType, rep);
            } else if (elemType == Integer.TYPE) {
                return new IntArrayDescriptor(type, elemType, rep);
            } else if (elemType == Long.TYPE) {
                return new LongArrayDescriptor(type, elemType, rep);
            } else if (elemType == Float.TYPE) {
                return new FloatArrayDescriptor(type, elemType, rep);
            } else if (elemType == Double.TYPE) {
                return new DoubleArrayDescriptor(type, elemType, rep);
            } else {
                throw new RuntimeException("unknown array type " + type);
            }
        }
        if (Serializable.class.equals(elemType) ||
                Externalizable.class.equals(elemType) || Object.class.equals(elemType)) {
            return new ObjectArrayDescriptor(type, elemType, rep);
        } else if (Remote.class.isAssignableFrom(elemType)) {
            return new RemoteArrayDescriptor(type, elemType, rep);
        } else if (Serializable.class.isAssignableFrom(elemType)) {
            return new ValueArrayDescriptor(type, elemType, rep);
        } else {
            return new AbstractObjectArrayDescriptor(type, elemType, rep);
        }
    }

    /**
     * Read an instance of this value from a CDR stream. Overridden to provide a
     * specific type
     */
    @Override
    public Object read(InputStream in) {
        org.omg.CORBA_2_3.portable.InputStream _in = (org.omg.CORBA_2_3.portable.InputStream) in;
        logger.fine("Reading an array value with repository id " + getRepositoryID() + " java class is " + type);

        // if we have a resolved class, read using that, otherwise fall back on the
        // repository id.
        return ((null == type) ? _in.read_value(getRepositoryID()) : _in.read_value(type));
    }

    /** Write an instance of this value to a CDR stream */
    @Override
    public void write(OutputStream out, Object value) {
        org.omg.CORBA_2_3.portable.OutputStream _out = (org.omg.CORBA_2_3.portable.OutputStream) out;

        _out.write_value((Serializable)value, getRepositoryID());
    }

    ValueMember[] getValueMembers() {

        if (_value_members == null) {

            _value_members = new ValueMember[1];

            TypeDescriptor elemDesc = repo.getDescriptor(elementType);

            String elemRepID = elemDesc.getRepositoryID();

            ORB orb = ORB.init();
            TypeCode memberTC = orb.create_sequence_tc(0, elemDesc
                    .getTypeCode());

            _value_members[0] = new ValueMember("", // member has no name!
                    elemRepID, this.getRepositoryID(), "1.0", memberTC, null,
                    (short) 1);
            // public
        }

        return _value_members;
    }

    @Override
    void addDependencies(Set classes) {
        repo.getDescriptor(basicType).addDependencies(classes);
    }

    final CorbaObjectReader makeCorbaObjectReader(final InputStream in, final Map offsetMap, final Serializable obj)
            throws IOException {
        try {
            return AccessController.doPrivileged(new PrivilegedExceptionAction<CorbaObjectReader>() {
                public CorbaObjectReader run() throws IOException {
                    return new CorbaObjectReader(in, offsetMap, obj);
                }
            });
        } catch (PrivilegedActionException e) {
            throw (IOException)e.getException();
        }
    }
}

class ObjectArrayDescriptor extends ArrayDescriptor {
    static Logger logger = Logger.getLogger(ArrayDescriptor.class.getName());

    ObjectArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public void writeValue(OutputStream out, Serializable value) {
        // System.out.println ("ObjectArrayDescriptor::writeValue
        // "+getRepositoryID ());

        Object[] arr = (Object[]) value;
        out.write_long(arr.length);

        logger.finer("writing " + type.getName() + " size="
                + arr.length);

        for (int i = 0; i < arr.length; i++) {
            javax.rmi.CORBA.Util.writeAny(out, arr[i]); 
        }
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        try {
            ObjectReader reader = makeCorbaObjectReader(in, offsetMap, null);

            int length = reader.readInt();
            Object[] arr = (Object[]) Array.newInstance(elementType, length);

            offsetMap.put(key, arr);

            logger.fine("reading " + type.getName() + " size="
                    + arr.length);

            for (int i = 0; i < length; i++) {
                try {
                    arr[i] = reader.readAny();
                    if (arr[i] != null) {
                        logger.finer("Array item " + i + " is of type " + arr[i].getClass().getName()); 
                    }
                    else {
                        logger.finer("Array item " + i + " is null"); 
                    }
                } catch (IndirectionException ex) {
                    arr[i] = offsetMap.get(new Integer(ex.offset));
                    // reader.addValueBox (ex.offset, new ArrayBox (i, arr));
                }
            }
            return arr;

        } catch (IOException ex) {
            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
        }

    }

    @Override
    Object copyObject(Object value, CopyState state) {
        final Object[] orig = (Object[]) value;
        final Object[] result = new Object[orig.length];
        state.put(value, result);

        for (int i = 0; i < orig.length; i++) {
            try {
                result[i] = state.copy(orig[i]);
            } catch (CopyRecursionException e) {
                final int idx = i;

                state.registerRecursion(new CopyRecursionResolver(orig[i]) {
                    public void resolve(Object value) {
                        result[idx] = value;
                    }
                });
            }
        }

        return result;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        Object[] arr = (Object[]) val;
        TypeDescriptor desc = repo.getDescriptor(elementType);
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            desc.print(pw, recurse, arr[i]);
        }
    }

}

class RemoteArrayDescriptor extends ArrayDescriptor {
    RemoteArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        Object[] arr = (Object[]) value;
        out.write_long(arr.length);
        for (int i = 0; i < arr.length; i++) {
            javax.rmi.CORBA.Util.writeRemoteObject(out, arr[i]);
        }
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        try {
            ObjectReader reader = makeCorbaObjectReader(in, offsetMap, null);

            int length = reader.readInt();
            Object[] arr = (Object[]) Array.newInstance(elementType, length);
            offsetMap.put(key, arr);

            for (int i = 0; i < length; i++) {
                try {
                    arr[i] = reader.readRemoteObject(elementType);
                } catch (IndirectionException ex) {
                    arr[i] = offsetMap.get(new Integer(ex.offset));
                    // reader.addValueBox (ex.offset, new ArrayBox (i, arr));
                }
            }

            return arr;

        } catch (IOException ex) {
            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
        }

    }

    @Override
    Object copyObject(Object value, CopyState state) {
        final Object[] orig = (Object[]) value;
        final Object[] result = (Object[]) Array.newInstance(elementType,
                orig.length);

        state.put(value, result);
        for (int i = 0; i < orig.length; i++) {
            try {
                result[i] = state.copy(orig[i]);
            } catch (CopyRecursionException e) {
                final int idx = i;

                state.registerRecursion(new CopyRecursionResolver(orig[i]) {
                    public void resolve(Object value) {
                        result[idx] = value;
                    }
                });
            }
        }

        return result;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        Object[] arr = (Object[]) val;
        TypeDescriptor desc = repo.getDescriptor(elementType);
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            desc.print(pw, recurse, arr[i]);
        }
    }
}

class ValueArrayDescriptor extends ArrayDescriptor {

    ValueArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        Object[] arr = (Object[]) value;
        out.write_long(arr.length);
        Serializable[] sarr = (Serializable[]) arr;
        org.omg.CORBA_2_3.portable.OutputStream _out = (org.omg.CORBA_2_3.portable.OutputStream) out;
        for (int i = 0; i < sarr.length; i++) {
            _out.write_value(sarr[i], getElementRepositoryID());
        }
    }

    @Override
    public Serializable readValue(InputStream in, Map offsetMap, Integer key) {
        final int length = in.read_long();
        Object[] arr = (Object[]) Array.newInstance(elementType, length);
        offsetMap.put(key, arr);

        final org.omg.CORBA_2_3.portable.InputStream _in = (org.omg.CORBA_2_3.portable.InputStream) in;
        for (int i = 0; i < length; i++) {
            try {
                arr[i] = _in.read_value(elementType);
            } catch (IndirectionException ex) {
                arr[i] = offsetMap.get(new Integer(ex.offset));
            }
        }

        return arr;
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        Object[] orig = (Object[]) value;
        final Object[] result = (Object[]) Array.newInstance(value.getClass()
                .getComponentType(), orig.length);

        state.put(value, result);
        for (int i = 0; i < orig.length; i++) {
            try {
                result[i] = state.copy(orig[i]);
            } catch (CopyRecursionException e) {
                final int idx = i;

                state.registerRecursion(new CopyRecursionResolver(orig[i]) {
                    public void resolve(Object value) {
                        result[idx] = value;
                    }
                });
            }
        }

        return result;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        Object[] arr = (Object[]) val;
        TypeDescriptor desc = repo.getDescriptor(elementType);
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            desc.print(pw, recurse, arr[i]);
        }
    }

}

class AbstractObjectArrayDescriptor extends ArrayDescriptor {
    AbstractObjectArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {

        Object[] arr = (Object[]) value;
        out.write_long(arr.length);
        for (int i = 0; i < arr.length; i++) {
            javax.rmi.CORBA.Util.writeAbstractObject(out, arr[i]);
        }
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        try {
            ObjectReader reader = makeCorbaObjectReader(in, offsetMap, null);

            int length = reader.readInt();
            Object[] arr = (Object[]) Array.newInstance(elementType, length);

            offsetMap.put(key, arr);

            for (int i = 0; i < length; i++) {
                try {
                    arr[i] = reader.readAbstractObject();
                } catch (IndirectionException ex) {
                    arr[i] = offsetMap.get(new Integer(ex.offset));
                    // reader.addValueBox (ex.offset, new ArrayBox (i, arr));
                }
            }

            return arr;

        } catch (IOException ex) {
            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
        }
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        final Object[] orig = (Object[]) value;
        final Object[] result = (Object[]) Array.newInstance(elementType,
                orig.length);

        state.put(value, result);
        for (int i = 0; i < orig.length; i++) {
            try {
                result[i] = state.copy(orig[i]);
            } catch (CopyRecursionException e) {
                final int idx = i;

                state.registerRecursion(new CopyRecursionResolver(orig[i]) {
                    public void resolve(Object value) {
                        result[idx] = value;
                    }
                });
            }
        }

        return result;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        Object[] arr = (Object[]) val;
        TypeDescriptor desc = repo.getDescriptor(elementType);
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            desc.print(pw, recurse, arr[i]);
        }
    }

}

class BooleanArrayDescriptor extends ArrayDescriptor {
    BooleanArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        boolean[] arr = new boolean[in.read_long()];
        offsetMap.put(key, arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.read_boolean();
        }
        return arr;
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        boolean[] arr = (boolean[]) value;
        out.write_long(arr.length);
        for (int i = 0; i < arr.length; i++) {
            out.write_boolean(arr[i]);
        }
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        if (((boolean[]) value).length == 0)
            return value;

        Object copy = ((boolean[]) value).clone();
        state.put(value, copy);
        return copy;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        boolean[] arr = (boolean[]) val;
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            pw.print(arr[i]);
        }
    }

}

class ByteArrayDescriptor extends ArrayDescriptor {
    ByteArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        byte[] arr = new byte[in.read_long()];
        offsetMap.put(key, arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.read_octet();
        }
        return arr;
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        byte[] arr = (byte[]) value;
        out.write_long(arr.length);

        out.write_octet_array(arr, 0, arr.length);
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        if (((byte[]) value).length == 0)
            return value;

        Object copy = ((byte[]) value).clone();
        state.put(value, copy);
        return copy;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        byte[] arr = (byte[]) val;
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            pw.print(arr[i]);
        }
    }
}

class CharArrayDescriptor extends ArrayDescriptor {
    CharArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        int len = in.read_long();
        char[] arr = new char[len];
        offsetMap.put(key, arr);
        in.read_wchar_array(arr, 0, len);
        return arr;
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        char[] arr = (char[]) value;
        out.write_long(arr.length);
        out.write_wchar_array(arr, 0, arr.length);
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        if (((char[]) value).length == 0)
            return value;

        Object copy = ((char[]) value).clone();
        state.put(value, copy);
        return copy;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        char[] arr = (char[]) val;
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            pw.print(arr[i]);
        }
    }
}

class ShortArrayDescriptor extends ArrayDescriptor {
    ShortArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        short[] arr = new short[in.read_long()];
        offsetMap.put(key, arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.read_short();
        }
        return arr;
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        short[] arr = (short[]) value;
        out.write_long(arr.length);
        for (int i = 0; i < arr.length; i++) {
            out.write_short(arr[i]);
        }
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        if (((short[]) value).length == 0)
            return value;

        Object copy = ((short[]) value).clone();
        state.put(value, copy);
        return copy;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        short[] arr = (short[]) val;
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            pw.print(arr[i]);
        }
    }
}

class IntArrayDescriptor extends ArrayDescriptor {
    IntArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        int[] arr = new int[in.read_long()];
        offsetMap.put(key, arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.read_long();
        }
        return arr;
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        int[] arr = (int[]) value;
        out.write_long(arr.length);
        for (int i = 0; i < arr.length; i++) {
            out.write_long(arr[i]);
        }
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        if (((int[]) value).length == 0)
            return value;

        Object copy = ((int[]) value).clone();
        state.put(value, copy);
        return copy;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        int[] arr = (int[]) val;
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            pw.print(arr[i]);
        }
    }
}

class LongArrayDescriptor extends ArrayDescriptor {
    LongArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        long[] arr = new long[in.read_long()];
        offsetMap.put(key, arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.read_longlong();
        }
        return arr;
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        long[] arr = (long[]) value;
        out.write_long(arr.length);
        for (int i = 0; i < arr.length; i++) {
            out.write_longlong(arr[i]);
        }
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        if (((long[]) value).length == 0)
            return value;

        Object copy = ((long[]) value).clone();
        state.put(value, copy);
        return copy;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        long[] arr = (long[]) val;
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            pw.print(arr[i]);
        }
    }

}

class FloatArrayDescriptor extends ArrayDescriptor {
    FloatArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        float[] arr = new float[in.read_long()];
        offsetMap.put(key, arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.read_float();
        }
        return arr;
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        float[] arr = (float[]) value;
        out.write_long(arr.length);
        for (int i = 0; i < arr.length; i++) {
            out.write_float(arr[i]);
        }
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        if (((float[]) value).length == 0)
            return value;

        Object copy = ((float[]) value).clone();
        state.put(value, copy);
        return copy;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        float[] arr = (float[]) val;
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            pw.print(arr[i]);
        }
    }
}

class DoubleArrayDescriptor extends ArrayDescriptor {
    DoubleArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
        super(type, elemType, rep);
    }

    @Override
    public Serializable readValue(
            InputStream in, Map offsetMap,
            Integer key) {
        double[] arr = new double[in.read_long()];
        offsetMap.put(key, arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.read_double();
        }
        return arr;
    }

    @Override
    public void writeValue(OutputStream out,
            Serializable value) {
        double[] arr = (double[]) value;
        out.write_long(arr.length);
        for (int i = 0; i < arr.length; i++) {
            out.write_double(arr[i]);
        }
    }

    @Override
    Object copyObject(Object value, CopyState state) {
        if (((double[]) value).length == 0)
            return value;

        Object copy = ((double[]) value).clone();
        state.put(value, copy);
        return copy;
    }

    @Override
    void printFields(PrintWriter pw, Map recurse, Object val) {
        double[] arr = (double[]) val;
        pw.print("length=" + arr.length + "; ");
        for (int i = 0; i < arr.length; i++) {
            if (i != 0) {
                pw.print(", ");
            }
            pw.print(arr[i]);
        }
    }
}
