Package org.squarebrackets

Source Code of org.squarebrackets.MutableDoubleBufferArrayImpl$ArrayIteratorImpl

/*
* ============================================================================
* GNU Lesser General Public License
* ============================================================================
*
* Square Brackets - Java Array Framework.
* Copyright (C) 2013  Beatgrid Media B.V.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
*
* Beatgrid Media B.V.
* Sisalbaan 5-A
* 2352 AZ Leiderdorp
* The Netherlands
*
* info@squarebrackets.org
* http://squarebrackets.org
*/
package org.squarebrackets;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.util.Comparator;
import java.util.NoSuchElementException;

/**
* <p>Fixed-size mutable wrapper for {@code DoubleBuffer}s.</p>
*
* <p>This mutable double array is constructed by the static interface methods of {@code MutableDoubleArray}.
* The {@code valueOf} methods wrap a new {@code MutableDoubleArray} around a buffer.</p>
*
* <p>Arrays express characteristics to indicate that, for instance, elements are listed in sorted order, or no
* duplicate elements exist. These characteristics allow array implementations to optimize their algorithms based
* on the contents of the array. For example, operations that lookup elements can use a binary search algorithm if
* the array is marked as being sorted. These optimizations may reduce the time complexity of such operations by
* several orders of magnitude.
* Mutable primitive arrays, such as this class, always report {@code MUTABLE} and {@code NONNULL}.</p>
*
* <p>This class attempts to establish these characteristics to accommodate these optimizations at best effort. This
* means that this implementation determines which set of characteristics apply to its elements without traversing these
* elements, in other words, without incurring a performance penalty. Characteristics are always invalidated if
* conditions of these characteristics are broken as result of array modification. Characteristics are only added in
* scenarios in which their conditions can be 'tested' without traversal of elements. For example, the {@code SORTED}
* characteristic is added if the length of an array is reduced to zero or one element, or if all elements are replaced
* by an array that is marked as being sorted. The semantics of characteristics processing is documented for each
* "destructive" method. Users can take full control of characteristics assignment by means of the
* {@link org.squarebrackets.MutableArray#doAction(org.squarebrackets.ArrayAction)} method.</p>
*
* @author Leon van Zantvoort
*/
@NotThreadSafe
class MutableDoubleBufferArrayImpl extends DoubleBufferArrayImpl implements MutableDoubleArray, MutableArrayCharacteristics<Double> {

    /** Is {@code true} if control is transferred to caller of {@code doAction}. */
    protected transient boolean inAction;

    /** Allows caller of {@code doAction} to control state of array. */
    private transient ArrayContext<Double> context;

    /**
     * Package visible constructor.
     *
     * @param buffer backing buffer.
     * @param characteristics array characteristics.
     * @param duplicate {@code true} to duplicate the {@code buffer}, {@code false} to use {@code buffer} reference
     *                  as backing buffer.
     * @throws IllegalArgumentException if buffer is read only.
     * @throws NullPointerException if the specified array is null.
     */
    MutableDoubleBufferArrayImpl(@Nonnull DoubleBuffer buffer, int characteristics, boolean duplicate) {
        super(buffer, characteristics, duplicate);
        if (buffer.isReadOnly()) {
            throw new IllegalArgumentException("Buffer is read only.");
        }
    }

    /**
     * Returns the array context of this array, or {@code null} if control is already transferred to caller of
     * {@code doAction}.
     *
     * @return array context.
     */
    protected ArrayContext<Double> getArrayContext() {
        if (inAction) {
            return null;
        }
        if (context == null) {
            context = new ArrayContextImpl();   // Lazy initialization.
        }
        return context;
    }

    /**
     * Updates the SORTED and DISTINCT characteristics of this array by looking at the elements surrounding the
     * specified {@code value}. The SORTED and/or DISTINCT characteristics are removed if the value invalidates the
     * characteristics. This method must only be invoked when this array reports the {@code SORTED} characteristic.
     *
     * @param elementIndex index relative to the backing buffer.
     * @param value value that is stored at index.
     */
    protected void updateCharacteristics(int elementIndex, double value) {
        assert hasCharacteristics(SORTED);
        if (elements.remaining() > 1) {
            if (elementIndex > elements.position()) {
                if (value < elements.get(elementIndex - 1)) {
                    removeCharacteristics(SORTED | DISTINCT);
                } else if (value == elements.get(elementIndex - 1)) {
                    removeCharacteristics(DISTINCT);
                }
            }
            if (elementIndex < elements.limit() - 1) {
                if (value > elements.get(elementIndex + 1)) {
                    removeCharacteristics(SORTED | DISTINCT);
                } else if (value == elements.get(elementIndex + 1)) {
                    removeCharacteristics(DISTINCT);
                }
            }
        }
    }

    /**
     * Updates the SORTED and DISTINCT characteristics of this array by looking at the elements surrounding the
     * first and last element of the specified {@code array}. The SORTED and/or DISTINCT characteristics are removed if
     * these elements invalidate the characteristics.
     *
     * @param elementIndex index relative to the backing buffer.
     * @param array array that is stored, starting at index.
     */
    protected void updateCharacteristics(int elementIndex, @Nonnull Array<? extends Double> array) {
        assert hasCharacteristics(SORTED);
        int len = array.length();
        if (elements.remaining() > len) {
            if (len > 0) {
                updateCharacteristics(elementIndex, elements.get(elementIndex));
            }
            if (len > 1) {
                if (hasCharacteristics(SORTED)) {
                    updateCharacteristics(elementIndex + len - 1, elements.get(elementIndex + len - 1));
                }
            }
        }
    }

    /**
     * Sets the specified characteristics for this array.
     *
     * @param characteristics characteristics to be set for this array.
     * @return the characteristics that were actually stored for this array.
     */
    @Override
    public int characteristics(int characteristics) {
        if (!inAction) {
            this.characteristics = filterCharacteristics(characteristics);
        }
        return this.characteristics;
    }

    /**
     * Allow array implementation to filter characteristics based on array specific logic.
     *
     * <p>Default implementation passes specified value straight through.</p>
     *
     * @param characteristics characteristics to be filtered.
     * @return the filtered characteristics.
     */
    @Override
    protected int filterCharacteristics(int characteristics) {
        return (characteristics | NONNULL | MUTABLE) & ~(RESIZABLE | REPLACEABLE);
    }

    /**
     * Performs the specified {@code action} without affecting the array's set of characteristics. Ownership of
     * array characteristics control is moved to the caller by means of the {@code ArrayContext} object. Errors or
     * runtime exceptions thrown by the action are relayed to the caller.
     *
     * @param <T> return type.
     * @param action the action to be performed.
     * @return the value returned by the action's {@code run} method.
     * @throws IllegalStateException if action is called when array does not own control of characteristics.
     * @exception NullPointerException if the action is {@code null}.
     */
    @SuppressWarnings("InconsistentJavaDoc")
    @Override
    public final <T> T doAction(@Nonnull ArrayAction<Double, T> action) {
        ArrayContext<Double> context = getArrayContext();
        if (context == null) {
            throw new IllegalStateException("Already in action.");
        }
        try {
            inAction = true;
            return action.run(context);
        } finally {
            inAction = false;
        }
    }

    /**
     * Returns the backing array (optional operation). All elements of {@code this} mutable array and parents of this
     * mutable array are stored in the returned object. Modifications to the backing array are reflected by {@code this}
     * mutable array and it's parents.
     *
     * <p>The resulting object must be cast to the primitive or object type of the implementing class.</p>
     *
     * <p><strong>Characteristics:</strong></p>
     *
     * <p>This method allows the caller to modify this array outside the scope of the implementing class. Hence, it can
     * not guarantee correctness of the characteristics of this array. For that reason, content related characteristics
     * (such as {@code SORTED} and {@code DISTINCT}) are removed by calling this method.
     * Characteristics removal can be suppressed by obtaining the backing array through {@code doAction}:</p>
     *
     * <pre>
     *{@literal double[] backingArray = (double[]) array.doAction(ArrayContext::array);}</pre>
     *
     * @return backing array.
     * @throws UnsupportedOperationException if array does not expose backing array.
     */
    @Override
    public double[] array() {
        if (elements.hasArray()) {
            characteristics(0);
            return elements.array();
        }
        throw new UnsupportedOperationException("Backing array not exposed by buffer.");
    }

    /**
     * Returns a duplicate of the backing buffer (optional operation). All elements of {@code this} array and parents of
     * this array are shared by this buffer. Changes to the buffer's content will be visible in this array, and vice
     * versa; the buffers' position, limit, and mark values will be independent.
     *
     * <p><strong>Characteristics:</strong></p>
     *
     * <p>This method allows the caller to modify the buffer outside the scope of the implementing class. Hence, it can
     * not guarantee correctness of the characteristics of this array. For that reason, content related
     * characteristics (such as {@code NONNULL}, {@code SORTED} and {@code DISTINCT}) are removed by calling this method.
     * Characteristics removal can be suppressed by obtaining the backing buffer through {@code doAction}. The buffer
     * obtained through {@code doAction} is the actual backing buffer instance, giving the caller full control over
     * the buffer's position, limit and mark values. Changes to these values, directly, or in directly (i.e., through
     * {@code get()} or {@code put()}) are reflected by {@code this} array. It is therefore advised to obtain a
     * duplicate of the buffer as demonstrated below, unless such changes are intentional.</p>
     *
     * <pre>
     *{@literal DoubleBuffer backingBuffer = (DoubleBuffer) array.doAction(ArrayContext::buffer).duplicate();}</pre>
     *
     * @return duplicate of the backing buffer.
     * @throws UnsupportedOperationException if array is not backed by a buffer.
     */
    @Override
    public DoubleBuffer buffer() {
        characteristics(0);
        return elements.duplicate();
    }

    /**
     * Sets the comparator that is used for sorting this array, {@code null} if array is sorted according to natural
     * ordering of elements, or {@code null} if array is not sorted.
     *
     * @param comparator the {@code Comparator} used to compare array elements. A {@code null} value indicates that the
     *                   elements' <i>Comparable natural ordering</i> is be used.
     * @throws UnsupportedOperationException if array is a primitive array.
     */
    @Override
    public void setComparator(@Nullable Comparator<? super Double> comparator) {
        throw new UnsupportedOperationException("Comparator not support for primitive arrays.");
    }

    /**
     * Replaces element at specified {@code index} by specified object.
     *
     * <p><strong>Characteristics:</strong></p>
     *
     * <p>Modification of this array may affect this array's characteristics. The array implementations of the
     * Java Array Framework, as returned by the static factory methods, adhere to the characteristics contract:</p>
     *
     * <ul>
     *   <li>if this array reports {@code SORTED} prior to this call, {@code SORTED} is reported after this
     *   invocation if the specified {@code object} does not break the sorted order of this array. Arrays
     *   sorted according to natural order are not regarded sorted if they contain {@code null} element(s);</li>
     *   <li>if this array reports {@code SORTED} and {@code DISTINCT} prior to this call, {@code DISTINCT} is
     *   reported after this invocation if the specified {@code object} was not already present in this array.</li>
     * </ul>
     *
     * @param index index of item to be replaced, relative to the offset of the array.
     * @param object object to replace existing value.
     * @return object that is replaced.
     * @throws IndexOutOfBoundsException if {@code index} position is invalid.
     * @throws NullPointerException if the specified {@code object} is null.
     */
    @SuppressWarnings("InconsistentJavaDoc")
    @Override
    public Double set(int index, Double object) {
        if (Tripwire.ENABLED) {
            Tripwire.trip(getClass());
        }
        return setDouble(index, object);
    }

    /**
     * Replaces element at specified {@code index} by specified double value.
     *
     * <p><strong>Characteristics:</strong></p>
     *
     * <p>Modification of this array may affect this array's characteristics. The array implementations of the
     * Java Array Framework, as returned by the static factory methods, adhere to the characteristics contract:</p>
     *
     * <ul>
     *   <li>if this array reports {@code SORTED} prior to this call, {@code SORTED} is reported after this
     *   invocation if the specified {@code object} does not break the sorted order of this array;</li>
     *   <li>if this array reports {@code SORTED} and {@code DISTINCT} prior to this call, {@code DISTINCT} is
     *   reported after this invocation if the specified {@code object} was not already present in this array.</li>
     * </ul>
     *
     * @param index index relative to the offset of the array.
     * @param value double value to replace existing value.
     * @return double value that is replaced.
     * @throws IndexOutOfBoundsException if {@code index} position is invalid.
     */
    @Override
    public double setDouble(int index, double value) {
        int elementIndex = elements.position() + index;
        double oldValue = elements.get(elementIndex);
        elements.put(elementIndex, value);
        if (hasCharacteristics(SORTED)) {
            updateCharacteristics(elementIndex, value);
        }
        return oldValue;
    }

    /**
     * Replaces all elements of this array by the elements of the specified array. Note that the length of {@code array}
     * needs to be equal to the length of this array.
     *
     * <p><strong>Characteristics:</strong></p>
     *
     * <p>Modification of this array may affect the array's characteristics. The array implementations of the
     * Java Array Framework, as returned by the static factory methods, adhere to the characteristics contract:</p>
     *
     * <ul>
     *   <li>if the specified {@code array} reports {@code SORTED}, {@code SORTED} is reported after this invocation if
     *   the comparator of the specified {@code array} is equal to this array's comparator;</li>
     *   <li>if the specified {@code array} reports {@code SORTED} and {@code DISTINCT}, {@code DISTINCT} is reported
     *   after this invocation if the comparator of the specified {@code array} is equal to this array's comparator.
     * </ul>
     *
     * @param array array to replace elements of this array.
     * @throws NullPointerException if the specified array is null or if the array contains null elements and this
     * array does not permit null elements.
     * @throws IllegalStateException if length of the specified array is not equal to length of this array.
     */
    @SuppressWarnings("InconsistentJavaDoc")
    @Override
    public void setAll(@Nonnull Array<? extends Double> array) {
        int offset = elements.position();
        int length = elements.remaining();
        int lengthDiff = array.length() - length;
        if (lengthDiff == 0) {
            DoubleArray cast = ArrayCast.toDoubleArray(array);
            if (cast != null && elements.hasArray()) {
                cast.toArray(elements.array(), elements.arrayOffset() + offset, length);
            } else {
                elements.mark();
                elements.put(NativeArrays.toDoubleArray(array), 0, length).reset();
            }
            characteristics(array.characteristics());   // All elements are replaced by new array; Copy characteristics.
            if (hasCharacteristics(SORTED)) {
                if (array.getComparator() != null) {
                    removeCharacteristics(SORTED | DISTINCT);
                } else {
                    updateCharacteristics(offset, array);
                }
            }
        } else {
            throw new IllegalStateException("Array length.");
        }
    }

    /**
     * Sorts this array according to natural ordering.
     *
     * <p><strong>Characteristics:</strong></p>
     *
     * <p>Modification of this array may affect the array's characteristics. The array implementations of the
     * Java Array Framework, as returned by the static factory methods, adhere to the characteristics contract:</p>
     *
     * <ul>
     *   <li>{@code SORTED} is reported after this invocation.</li>
     * </ul>
     */
    @SuppressWarnings("InconsistentJavaDoc")
    @Override
    public void sort() {
        if (!hasCharacteristics(SORTED)) {
            if (elements.hasArray()) {
                int arrayOffset = elements.arrayOffset();
                java.util.Arrays.sort(elements.array(), arrayOffset + elements.position(), arrayOffset + elements.limit());
            } else {
                double[] a = toArray();
                java.util.Arrays.sort(a);
                elements.mark();
                elements.put(a).reset();
            }
            addCharacteristics(SORTED)// Array is guaranteed to be sorted.
        }
    }

    /**
     * Sorts this array according to natural ordering. The underlying implementation utilizes multiple threads
     * to reduce sorting time. The algorithm may require a working space equal to the size of this array.
     *
     * <p><strong>Characteristics:</strong></p>
     *
     * <p>Modification of this array may affect the array's characteristics. The array implementations of the
     * Java Array Framework, as returned by the static factory methods, adhere to the characteristics contract:</p>
     *
     * <ul>
     *   <li>{@code SORTED} is reported after this invocation.</li>
     * </ul>
     */
    @SuppressWarnings("InconsistentJavaDoc")
    @Override
    public void parallelSort() {
        if (!hasCharacteristics(SORTED)) {
            if (elements.hasArray()) {
                int arrayOffset = elements.arrayOffset();
                java.util.Arrays.parallelSort(elements.array(), arrayOffset + elements.position(), arrayOffset + elements.limit());
            } else {
                double[] a = toArray();
                java.util.Arrays.parallelSort(a);
                elements.mark();
                elements.put(a).reset();
            }
            addCharacteristics(SORTED)// Array is guaranteed to be sorted.
        }
    }

    /**
     * Array context implementation.
     */
    @SuppressWarnings("MissingMethodJavaDoc")
    private class ArrayContextImpl implements ArrayContext<Double> {

        void checkState() {
            if (!inAction) {
                throw new IllegalStateException("Not in action.");
            }
        }

        @Override
        public boolean hasArray() {
            checkState();
            return elements.hasArray();
        }

        @Override
        public Object array() {
            checkState();
            return elements.array();
        }

        @Override
        public boolean hasBuffer() {
            checkState();
            return true;
        }

        @Override
        public Buffer buffer() {
            checkState();
            return elements;
        }

        @Override
        public Class<? super Double> getComponentType() {
            checkState();
            return Double.TYPE;
        }

        @Override
        public int characteristics(int newCharacteristics) {
            checkState();
            return characteristics = filterCharacteristics(newCharacteristics);
        }

        @Override
        public int characteristics() {
            checkState();
            return characteristics;
        }

        @Override
        public @CheckForNull Comparator<? super Double> getComparator() {
            checkState();
            return null;
        }

        @Override
        public void setComparator(@Nullable Comparator<? super Double> comparator) {
            checkState();
            throw new UnsupportedOperationException();
        }
    }

    @SuppressWarnings({"MissingMethodJavaDoc", "MissingFieldJavaDoc"})
    private static class SubMutableDoubleBufferArrayImpl extends MutableDoubleBufferArrayImpl {

        final MutableDoubleBufferArrayImpl parent;

        SubMutableDoubleBufferArrayImpl(@Nonnull MutableDoubleBufferArrayImpl parent, @Nonnull DoubleBuffer buffer) {
            super(buffer, parent.characteristics, false);
            this.parent = parent;
        }

        @Override
        protected ArrayContext<Double> getArrayContext() {
            return parent.inAction ? null : super.getArrayContext();
        }

        @Override
        protected void updateCharacteristics(int elementIndex, double value) {
            super.updateCharacteristics(elementIndex, value);
            if (hasCharacteristics(SORTED)) {
                parent.updateCharacteristics(elementIndex, value);
            }
        }

        @Override
        protected void updateCharacteristics(int elementIndex, @Nonnull Array<? extends Double> array) {
            super.updateCharacteristics(elementIndex, array);
            if (hasCharacteristics(SORTED)) {
                parent.updateCharacteristics(elementIndex, array);
            }
        }

        @Override
        public int characteristics(int characteristics) {
            // Parent array retains characteristics that are shared with sub array. Additional characteristics
            // assigned to sub array are not set for parent array, as it is not guaranteed that these
            // characteristics hold for parent array.
            parent.retainCharacteristics(characteristics);
            return super.characteristics(characteristics);
        }
    }

    /**
     * <p>Returns a new sub array object for the specified {@code offset}. The specified {@code offset} is relative to
     * the existing offset, as returned by {@link #offset()}. The length of the resulting array is reduced by
     * the number of elements that are added to the current offset:</p>
     *
     * <pre>int newLength = length() - offset;</pre>
     *
     * <p>Effectively, the virtual {@code toIndex} of the array remains the same.</p>
     *
     * @param offset new relative offset.
     * @return a new sub array object with the new {@code offset}.
     */
    @Override
    public MutableDoubleArray offset(int offset) {
        if (offset == 0) {
            return this;
        }
        int newOffset = elements.position() + offset;
        int newLength = elements.remaining() - offset;
        subArrayCheck(newOffset, newLength);
        DoubleBuffer copy = elements.duplicate();
        copy.position(newOffset);
        return new SubMutableDoubleBufferArrayImpl(this, copy);
    }

    /**
     * <p>Returns a new sub array object for the specified {@code length}. Note that {@code length} must be smaller than
     * or equal to the current length, as returned by {@code #length}.</p>
     *
     * @param length new length, must be smaller than or equal to current length.
     * @return a new sub array object with the new {@code length}.
     */
    @Override
    public MutableDoubleArray length(int length) {
        if (elements.remaining() == length) {
            return this;
        }
        int offset = elements.position();
        subArrayCheck(offset, length);
        DoubleBuffer copy = elements.duplicate();
        copy.limit(offset + length);
        return new SubMutableDoubleBufferArrayImpl(this, copy);
    }

    /**
     * Convenience method, combining {@code offset(int)} and {@code length(int)}.
     *
     * @param fromIndex low endpoint (inclusive) of the sub array.
     * @param toIndex high endpoint (exclusive) of the sub array.
     * @return a view of the specified range within this array.
     * @throws IndexOutOfBoundsException for an illegal endpoint index value ({@code fromIndex < 0 || toIndex > length ||
     *         fromIndex > toIndex}).
     */
    @Override
    public MutableDoubleArray subArray(int fromIndex, int toIndex) {
        int offset = elements.position();
        int length = elements.remaining();
        int newOffset = offset + fromIndex;
        int newLength = toIndex - fromIndex;
        if (newOffset == offset && newLength == length) {
            return this;
        }
        subArrayCheck(newOffset, newLength);
        DoubleBuffer copy = elements.duplicate();
        copy.position(newOffset);
        copy.limit(newOffset + newLength);
        return new SubMutableDoubleBufferArrayImpl(this, copy);
    }

    @SuppressWarnings({"MissingMethodJavaDoc", "MissingFieldJavaDoc"})
    private class ArrayIteratorImpl implements ArrayIterator.OfDouble {
        int index;
        int lastIndex = -1;

        ArrayIteratorImpl() {
            this(0);
        }

        ArrayIteratorImpl(int index) {
            this.index = elements.position() + index;
        }

        @Override
        public boolean hasNext() {
            return index < elements.limit();
        }

        @Override
        public double nextDouble() {
            int i = index;
            if (i >= elements.limit()) {
                throw new NoSuchElementException();
            }
            index = i + 1;
            return elements.get(lastIndex = i);
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean hasPrevious() {
            return index > elements.position();
        }

        @Override
        public double previousDouble() {
            int i = index - 1;
            if (i < elements.position()) {
                throw new NoSuchElementException();
            }
            assert i < elements.limit();
            index = i;
            return elements.get(lastIndex = i);
        }

        @Override
        public int nextIndex() {
            return index;
        }

        @Override
        public int previousIndex() {
            return index - 1;
        }

        @Override
        public void setDouble(double value) {
            if (lastIndex < 0) {
                throw new IllegalStateException();
            }
            assert lastIndex < elements.limit();
            MutableDoubleBufferArrayImpl.this.set(lastIndex, value);
        }

        @Override
        public void addDouble(double value) {
            throw new UnsupportedOperationException();
        }
    }

    /**
     * Returns an array iterator over the elements in this array.
     *
     * @return an array iterator over the elements in this array.
     */
    @Override
    public ArrayIterator.OfDouble iterator() {
        return new ArrayIteratorImpl();
    }

    /**
     * Returns an array iterator over the elements in this array.
     *
     * @param index index of the first element to be returned from the array iterator.
     * @return a array iterator over the elements in this array.
     * @throws IndexOutOfBoundsException if the index is out of range.
     */
    @Override
    public ArrayIterator.OfDouble iterator(int index) {
        rangeCheckForIterator(index);
        return new ArrayIteratorImpl(index);
    }

    /**
     * Write replace method for the serialization proxy pattern. This method must be overwritten by sub classes if their
     * serialized form differs from this class.
     *
     * @return serialization proxy.
     */
    @Override
    Object writeReplace() {
        return new SerializationProxy(this);
    }

    @SuppressWarnings("MissingMethodJavaDoc")
    private void readObject(ObjectInputStream s) throws InvalidObjectException {
        throw new InvalidObjectException("Proxy required");
    }

    @SuppressWarnings({"MissingMethodJavaDoc", "MissingFieldJavaDoc"})
    private static class SerializationProxy implements Serializable {
        static final long serialVersionUID = 8219170256053125256L;

        final int length;
        final boolean direct;
        final int characteristics;
        transient DoubleBuffer elements;

        SerializationProxy(MutableDoubleBufferArrayImpl array) {
            this.length = array.elements.remaining();
            this.direct = array.elements.isDirect();
            this.characteristics = array.characteristics;
            this.elements = array.elements;
        }

        private void writeObject(ObjectOutputStream s) throws IOException {
            s.defaultWriteObject();
            elements.mark();
            for (int i = 0; i < length; i++) {
                s.writeDouble(elements.get());
            }
            elements.reset();
        }

        private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
            s.defaultReadObject();
            if (direct) {
                elements = ByteBuffer.allocateDirect(Double.SIZE / Byte.SIZE * length).asDoubleBuffer();
            } else {
                elements = DoubleBuffer.allocate(length);
            }
            for (int i = 0; i < length; i++) {
                elements.put(s.readDouble());
            }
            elements.rewind();
        }

        private Object readResolve() {
            return new MutableDoubleBufferArrayImpl(elements, characteristics, false);
        }
    }
}
TOP

Related Classes of org.squarebrackets.MutableDoubleBufferArrayImpl$ArrayIteratorImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.