/*
 * Copyright 1998-2004 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.tools.jdi;

import com.sun.jdi.*;

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

public class ArrayReferenceImpl extends ObjectReferenceImpl
    implements ArrayReference
{
    int length = -1;

    ArrayReferenceImpl(VirtualMachine aVm,long aRef) {
        super(aVm,aRef);
    }

    protected ClassTypeImpl invokableReferenceType(Method method) {
        // The method has to be a method on Object since
        // arrays don't have methods nor any other 'superclasses'
        // So, use the ClassTypeImpl for Object instead of
        // the ArrayTypeImpl for the array itself.
        return (ClassTypeImpl)method.declaringType();
    }

    ArrayTypeImpl arrayType() {
        return (ArrayTypeImpl)type();
    }

    /**
     * Return array length.
     * Need not be synchronized since it cannot be provably stale.
     */
    public int length() {
        if(length == -1) {
            try {
                length = JDWP.ArrayReference.Length.
                    process(vm, this).arrayLength;
            } catch (JDWPException exc) {
                throw exc.toJDIException();
            }
        }
        return length;
    }

    public Value getValue(int index) {
        List list = getValues(index, 1);
        return (Value)list.get(0);
    }

    public List<Value> getValues() {
        return getValues(0, -1);
    }

    /**
     * Validate that the range to set/get is valid.
     * length of -1 (meaning rest of array) has been converted
     * before entry.
     */
    private void validateArrayAccess(int index, int length) {
        // because length can be computed from index,
        // index must be tested first for correct error message
        if ((index < 0) || (index > length())) {
            throw new IndexOutOfBoundsException(
                        "Invalid array index: " + index);
        }
        if (length < 0) {
            throw new IndexOutOfBoundsException(
                        "Invalid array range length: " + length);
        }
        if (index + length > length()) {
            throw new IndexOutOfBoundsException(
                        "Invalid array range: " +
                        index + " to " + (index + length - 1));
        }
    }

    @SuppressWarnings("unchecked")
    private static <T> T cast(Object x) {
        return (T)x;
    }

    public List<Value> getValues(int index, int length) {
        if (length == -1) { // -1 means the rest of the array
           length = length() - index;
        }
        validateArrayAccess(index, length);
        if (length == 0) {
            return new ArrayList<Value>();
        }

        List<Value> vals;
        try {
            vals = cast(JDWP.ArrayReference.GetValues.process(vm, this, index, length).values);
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }

        return vals;
    }

    public void setValue(int index, Value value)
            throws InvalidTypeException,
                   ClassNotLoadedException {
        List<Value> list = new ArrayList<Value>(1);
        list.add(value);
        setValues(index, list, 0, 1);
    }

    public void setValues(List<? extends Value> values)
            throws InvalidTypeException,
                   ClassNotLoadedException {
        setValues(0, values, 0, -1);
    }

    public void setValues(int index, List<? extends Value> values,
                          int srcIndex, int length)
            throws InvalidTypeException,
                   ClassNotLoadedException {

        if (length == -1) { // -1 means the rest of the array
            // shorter of, the rest of the array and rest of
            // the source values
            length = Math.min(length() - index,
                              values.size() - srcIndex);
        }
        validateMirrorsOrNulls(values);
        validateArrayAccess(index, length);

        if ((srcIndex < 0) || (srcIndex > values.size())) {
            throw new IndexOutOfBoundsException(
                        "Invalid source index: " + srcIndex);
        }
        if (srcIndex + length > values.size()) {
            throw new IndexOutOfBoundsException(
                        "Invalid source range: " +
                        srcIndex + " to " +
                        (srcIndex + length - 1));
        }

        boolean somethingToSet = false;;
        ValueImpl[] setValues = new ValueImpl[length];

        for (int i = 0; i < length; i++) {
            ValueImpl value = (ValueImpl)values.get(srcIndex + i);

            try {
                // Validate and convert if necessary
                setValues[i] =
                  ValueImpl.prepareForAssignment(value,
                                                 new Component());
                somethingToSet = true;
            } catch (ClassNotLoadedException e) {
                /*
                 * Since we got this exception,
                 * the component must be a reference type.
                 * This means the class has not yet been loaded
                 * through the defining class's class loader.
                 * If the value we're trying to set is null,
                 * then setting to null is essentially a
                 * no-op, and we should allow it without an
                 * exception.
                 */
                if (value != null) {
                    throw e;
                }
            }
        }
        if (somethingToSet) {
            try {
                JDWP.ArrayReference.SetValues.
                    process(vm, this, index, setValues);
            } catch (JDWPException exc) {
                throw exc.toJDIException();
            }
        }
    }

    public String toString() {
        return "instance of " + arrayType().componentTypeName() +
               "[" + length() + "] (id=" + uniqueID() + ")";
    }

    byte typeValueKey() {
        return JDWP.Tag.ARRAY;
    }

    void validateAssignment(ValueContainer destination)
                            throws InvalidTypeException, ClassNotLoadedException {
        try {
            super.validateAssignment(destination);
        } catch (ClassNotLoadedException e) {
            /*
             * An array can be used extensively without the
             * enclosing loader being recorded by the VM as an
             * initiating loader of the array type. In addition, the
             * load of an array class is fairly harmless as long as
             * the component class is already loaded. So we relax the
             * rules a bit and allow the assignment as long as the
             * ultimate component types are assignable.
             */
            boolean valid = false;
            JNITypeParser destParser = new JNITypeParser(
                                       destination.signature());
            JNITypeParser srcParser = new JNITypeParser(
                                       arrayType().signature());
            int destDims = destParser.dimensionCount();
            if (destDims <= srcParser.dimensionCount()) {
                /*
                 * Remove all dimensions from the destination. Remove
                 * the same number of dimensions from the source.
                 * Get types for both and check to see if they are
                 * compatible.
                 */
                String destComponentSignature =
                    destParser.componentSignature(destDims);
                Type destComponentType =
                    destination.findType(destComponentSignature);
                String srcComponentSignature =
                    srcParser.componentSignature(destDims);
                Type srcComponentType =
                    arrayType().findComponentType(srcComponentSignature);
                valid = ArrayTypeImpl.isComponentAssignable(destComponentType,
                                                          srcComponentType);
            }

            if (!valid) {
                throw new InvalidTypeException("Cannot assign " +
                                               arrayType().name() +
                                               " to " +
                                               destination.typeName());
            }
        }
    }

    /*
     * Represents an array component to other internal parts of this
     * implementation. This is not exposed at the JDI level. Currently,
     * this class is needed only for type checking so it does not even
     * reference a particular component - just a generic component
     * of this array. In the future we may need to expand its use.
     */
    class Component implements ValueContainer {
        public Type type() throws ClassNotLoadedException {
            return arrayType().componentType();
        }
        public String typeName() {
            return arrayType().componentTypeName();
        }
        public String signature() {
            return arrayType().componentSignature();
        }
        public Type findType(String signature) throws ClassNotLoadedException {
            return arrayType().findComponentType(signature);
        }
    }
}
