/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.sdo.helper;

import commonj.sdo.DataObject;
import commonj.sdo.Property;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.Collection;
import java.util.ListIterator;
import org.eclipse.persistence.sdo.SDOChangeSummary;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;

/**
 * INTERNAL:
 * <p>
 * <b>Purpose:</b>
 * <ul><li>This class wraps the ArrayList of currentElements that implement the List interface.</li>
 * </ul>
 * <p>
 * <b>Responsibilities:</b>
 * <ul>
 * <li>Provide access many properties on {@link DataObject dataObject}s</li>
 * </ul>
 *
 * @see org.eclipse.persistence.sdo.SDODataObject
 * @since Oracle TopLink 11.1.1.0.0
 */
public class ListWrapper implements List, Serializable, Cloneable {

    /*
        05/23/06 - Update addAll(int,Collection), retainAll(Collection), set(int, Object),
                                         add(int, Object), remove(int)
        05/30/06 - SDO-55: JUnit test case adjustments
        07/27/06 - Add pluggable support for BC4J - make fields protected for *SDOList implementations
        08/21/06 - Remove null check on overloaded addAll()
        08/31/06 - Return instance variables to private state - SDOList has been removed
        01/03/07 - add(*) no longer running updateContainment on itself
        01/08/07 - add(object) - reverse order of and extract updateContainment call
                                                extract out common removeContainment from remove() - coverage from 97.5-99.4
        01/31/07 - add undo support by maintaining 2 internal lists
        02/04/07 - add undoChanges() to reset original elements
        02/08/07 - removed equals and hashCode methods as they seem to cause unexplained issues when we started using Listwrapper as a key in a map
        02/21/07 - #5895047: pass the recursive removeContainment flag fromDelete into remove() when called from detach()
                            This will invoke creation of an intact list copy before removing its containment and clearing its changeSummary
        04/16/07 - implement sequences
        04/25/07 - adding duplicate containment true dataObjects are ignored - only a single instance can exist
     */
    protected SDODataObject dataObject;
    protected SDOProperty property;

    /**
     * We are maintaining two pointers to potentially two ArrayList objects.
     * To implement ChangeSummary undo we require a copy of the original state of our model
     * - with special handling for ListWrapper to maintain object identity of the list
     * The List (originalElements) on ChangeSummary will maintain the current state of our model after logged changes.
     * The List (currentElements) will be a progressively deeper distinct shallow copy of the current list as it changes
     */
    protected List currentElements;

    /**
     * INTERNAL:
     * @return
     */
    private List getEmptyList() {
        // ArrayList will be our implementation of List for now - consolidate new calls here
        return new ArrayList();
    }

    public ListWrapper() {
        currentElements = getEmptyList();
    }

    public ListWrapper(SDODataObject theDataObject, Property theProperty) {
        this();
        dataObject = theDataObject;
        property = (SDOProperty) theProperty;
    }

    /**
     * Constructor for non-default Pluggable ValueStore implementations<br>
     * Prerequisites: Containment is already set on theList parameter.
     * Do not use this constructor for default implementations as containment is not updated.
     * The SDO Objects inside this ListWrapper are special case wrappers with no previous containment
     * We do not call updateContainment on the SDO Wrapper objects surrounding the POJO's
     * otherwise the containment of this list will be removed in the embedded detach() call
     * TestCase: the first get on a list.
     */
    public ListWrapper(SDODataObject theDataObject, Property theProperty, List theList) {
        this(theDataObject, theProperty);
        currentElements = theList;
    }

    /**
     *
     */
    @Override
    public boolean add(Object item) {
        return add(item, true);
    }

    /**
     * INTERNAL:
     * @param item
     * @param updateSequence
     * @return
     */
    public boolean add(Object item, boolean updateSequence) {
        // Not allowed to add null if the property is non-nullable
        if (item == null && (property != null && !property.isNullable())) {
            throw new UnsupportedOperationException("Property [" + property.getName() + "] is non-nullable");
        }

        // update element arrays before we modify original object
        copyElements();

        boolean result = currentElements.add(item);

        // update containment
        updateContainment(item, updateSequence);

        // update opposite property
        if (property != null && item != null) {
            Property oppositeProp = property.getOpposite();
            if (oppositeProp != null) {
                ((DataObject) item).set(oppositeProp, dataObject);
            }
        }

        return result;
    }

    /**
     * Inserts the specified element at the index position in this list.<br>
     * @param index (start at 0 = prepend, length = append)
     * @param item
     */
    @Override
    public void add(int index, Object item) {
        add(index, item, true);
    }

    /**
     * INTERNAL:
     * @param index
     * @param item
     * @param updateSequence
     */
    public void add(int index, Object item, boolean updateSequence) {
        // Not allowed to add null if the property is non-nullable
        if (item == null && (property != null && !property.isNullable())) {
            throw new UnsupportedOperationException("Property [" + property.getName() + "] is non-nullable");
        }

        // see testLitWrapperAddMaintainsContainment()
        // fail-fast range checking
        if ((index < 0) || (index > size())) {
            return;
        }

        // update element arrays before we modify original object
        copyElements();

        // delegate to superclass
        currentElements.add(index, item);

        // update containment
        updateContainment(item, updateSequence);

        // update opposite property
        if (property != null && item != null) {
            Property oppositeProp = property.getOpposite();
            if (oppositeProp != null) {
                ((DataObject) item).set(oppositeProp, dataObject);
                dataObject.set(oppositeProp, null);
            }
        }
    }

    /**
     * INTERNAL:
     */
    protected boolean isLogging() {
        return ((dataObject != null) && (dataObject.getChangeSummary() != null) && dataObject.getChangeSummary().isLogging());
    }

    /**
     * INTERNAL:
     * Shallow copy elements
     *
     */
    protected void copyElements() {
        // update element arrays before we modify original object
        if (isLogging() && (!dataObject.getChangeSummary().isDirty(this))) {
            // original will maintain object identity - swap before copying
            dataObject.getChangeSummary().getOriginalElements().put(this, currentElements);
            // current list will now be a shallow copy of original(itself) - we will not use ArrayList.clone()
            currentElements = new ArrayList(currentElements);
        }
    }

    /**
     * INTERNAL:
     * Undo any changes and return the original List
     */
    public void undoChanges(SDOChangeSummary cs) {
        // ignore logging state
        if (null == cs) {
            return;
        }
        if (cs.isDirty(this)) {
            // swap elements, discard current state
            currentElements = (List)cs.getOriginalElements().get(this);
            cs.getOriginalElements().remove(this);
        }
    }

    /**
     * INTERNAL:
     * Iterate the collection and add settings where appropriate.
     * @param aProperty
     * @param items
     * @param updateSequence
     */
    protected void updateSequence(Property aProperty, Collection items, boolean updateSequence) {
        if (updateSequence) {
            Iterator valuesIter = items.iterator();
            ArrayList duplicatesList = new ArrayList();// <DataObject>
            while (valuesIter.hasNext()) {
                Object next = valuesIter.next();

                // do not add duplicate settings for containment dataObjects
                if ((null != aProperty) && !((SDOProperty)aProperty).getType().isDataType() && aProperty.isContainment()) {// dataType and containment are mutually exclusive
                    if (!duplicatesList.contains(next)) {
                        updateSequenceSettingInternal(property, next);
                        duplicatesList.add(next);
                    }
                } else {
                    updateSequenceSettingInternal(property, next);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Update the sequence by appending an new setting containing this item object
     * @param item
     */
    private void updateSequenceSettingInternal(Property aProperty, Object item) {
        // create a new setting
        // Note: A non spec isSequenced=true after type define will throw a NPE
        if (dataObject.getType().isSequenced()) {
            dataObject.getSequence().addSettingWithoutModifyingDataObject(property, item);
        }
    }

    /**
     * INTERNAL:
     * Update the sequence by removing the setting containing this item object
     * @param item
     */
    private void removeSequenceSettingInternal(int occurrence, Property aProperty, Object item) {
        // get index corresponding to the property:value pair
        // Note: A non spec isSequenced=true after type define will throw a NPE
        if (dataObject.getType().isSequenced()) {
            dataObject.getSequence().removeSettingWithoutModifyingDataObject(property, item);
        }
    }

    /**
     * INTERNAL:
     * @param item
     * @param updateSequence
     */
    protected void updateContainment(Object item, boolean updateSequence) {
        if ((property != null) && property.isContainment() && item instanceof SDODataObject) {
            dataObject.updateContainment(property, (SDODataObject)item);
        } else {
            if(dataObject != null) {
                dataObject._setModified(true);
            }
        }
        // update sequence for containment and non-containment objects
        if ((property != null) && updateSequence) {
            updateSequenceSettingInternal(property, item);
        }
    }

    protected void updateContainment(Collection items, boolean updateSequence) {
        if ((property != null) && property.isContainment()) {
            dataObject.updateContainment(property, items, updateSequence);
        } else {
            if(dataObject != null) {
                dataObject._setModified(true);
            }
        }
    }

    /**
     * INTERNAL:
     * @param item
     * @param fromDelete
     * @param updateSequence
     */
    protected void removeContainment(Object item, boolean fromDelete, boolean updateSequence) {

        /**
         * Case multiple occurrences of a single item - which to remove?
         *         [0]    ItemImpl  (id=58) <- this one
         *         [1]    ItemImpl  (id=35)
         *         [2]    ItemImpl  (id=35)
        */

        // default to removing the first occurrence of item (as in the List interface)
        removeContainment(0, item, fromDelete, updateSequence);
    }

    /**
     * INTERNAL:
     * @param item
     * @param fromDelete
     * @param updateSequence
     */
    protected void removeContainment(int occurrence, Object item, boolean fromDelete, boolean updateSequence) {
        if ((property != null) && property.isContainment() && (item != null)) {
            // passing a false fromDelete flag will not remove containment
            ((SDODataObject)item).detachOrDelete(fromDelete);
        } else {
            dataObject._setModified(true);
        }
        if ((property != null) && dataObject.getType().isSequenced() && updateSequence) {
            removeSequenceSettingInternal(occurrence, property, item);
        }
    }

    /**
     * INTERNAL:
     * Remove the item or first occurrence of the item.
     * @param item
     * @param fromDelete
     * @param updateSequence
     * @return
     */
    public boolean remove(Object item, boolean fromDelete, boolean updateSequence) {
        // update element arrays before we modify original object
        copyElements();
        // pass the remove containment (fromDelete) flag back to the recursive delete/detach call to dataObject
        // fromDelete will always be false when called within ListWrapper
        removeContainment(item, fromDelete, updateSequence);
        // remove the first occurrence of any duplicates
        return currentElements.remove(item);
    }

    /**
     * @param item
     * @return
     */
    @Override
    public boolean remove(Object item) {
        // remove item without removing containment
        return remove(item, false, true);
    }

    /**
     * Appends all of the currentElements in the specified Collection to the end of this list,
     * in the order that they are returned by the specified Collection's Iterator.
     * The behavior of this operation is undefined if the specified Collection is modified
     * while the operation is in progress. (This implies that the behavior of this call is undefined
     * if the specified Collection is this list, and this list is nonempty.)<br>
     * This operation is a special case of the general addAll(int, Collection).<br>
     *
     * From the SDO Specification: p18
     *  The getList(property) accessor is especially convenient for many-valued properties.
     *  If property.many is true then set(property, value) and setList(property, value)
     *  require that [value] be a java.util.Collection and List respectively.
     *  These methods are equivalent to getList(property).clear() followed by getList(property).addAll(value).
     *
     * @param items
     * @return boolean
     */
    @Override
    public boolean addAll(Collection items) {
        // Not allowed to add null if the property is non-nullable
        if (items.contains(null) && (property != null && !property.isNullable())) {
            throw new UnsupportedOperationException("Property [" + property.getName() + "] is non-nullable");
        }
        return addAll(items, true);
    }

    /**
     * INTERNAL:
     * Appends all of the currentElements in the specified Collection to the end of this list,
     * in the order that they are returned by the specified Collection's Iterator.
     * This function calls the public addAll(Collection) with a sequence state flag.
     * @param items
     * @param updateSequence
     * @return
     */
    public boolean addAll(Collection items, boolean updateSequence) {
        // update element arrays before we modify original object
        copyElements();

        /**
         * The order of operations for add is
         * 1 - add elements
         * 2 - update containment
         *
         * This order is the reverse of the order in remove
         * 1 - remove containment
         * 2 - remove elements
         */

        // add new elements before we have updated containment on the items - duplicates will be removed
        boolean modified = currentElements.addAll(items);

        // non-default Pluggable implementations do not require updateContainment
        dataObject._getCurrentValueStore().setManyProperty(property, this);

        /**
         * Corner case: Duplicate DataObjects
         * The effect of updateContainment on duplicates will be the removal of all but one of the duplicates
         * in the items collection that was added.
         * For sequences we must remove duplicates from items to match updateContainment for containment dataObjects
         */
           updateContainment(items, updateSequence);

        // update opposite property
        if (property != null) {
            Property oppositeProp = property.getOpposite();
            if (oppositeProp != null) {
                Iterator itemsIterator = items.iterator();
                while(itemsIterator.hasNext()) {
                    Object item = itemsIterator.next();
                    if (item != null) {
                        ((DataObject) item).set(oppositeProp, dataObject);
                    }
                }
            }
        }

        // create new settings outside of updateContainment as we do earlier in currentElements.add
        updateSequence(property, items, updateSequence);

        return modified;
    }

    /**
     * Inserts all of the currentElements in the specified Collection into this list, starting at the
     * specified position. Shifts the element currently at that position (if any)
     * and any subsequent currentElements to the right (increases their indices).
     * The new currentElements will appear in the list in the order that they are returned by the
     * specified Collection's iterator.<br>
     * @param position (start at 0 = prepend, length = append)
     * @param items
     * @return boolean
     */
    @Override
    public boolean addAll(int position, Collection items) {
        return addAll(position, items, true);
    }

    public boolean addAll(int position, Collection items, boolean updateSequence) {
        // fail-fast range checking
        if ((position < 0) || (position > size())) {
            return false;
        }
        if ((items == null) || (items.size() == 0)) {
            return false;
        }

        // Not allowed to add null if the property is non-nullable
        if (items.contains(null) && (property != null && !property.isNullable())) {
            throw new UnsupportedOperationException("Property [" + property.getName() + "] is non-nullable");
        }

        // delegate to superclass
        // update element arrays before we modify original object
        copyElements();

        /**
         * The order of operations for add is
         * 1 - add elements
         * 2 - update containment
         *
         * This order is the reverse of the order in remove
         * 1 - remove containment
         * 2 - remove elements
         */
        boolean modified = currentElements.addAll(position, items);

        /**
         * Corner case: Duplicate DataObjects
         * The effect of updateContainment on duplicates will be the removal of all but one of the duplicates
         * in the items collection that was added.
         * For sequences we must remove duplicates from items to match updateContainment for containment dataObjects
         */
        // update containment
        updateContainment(items, updateSequence);

        // update opposite property
        if (property != null) {
            Property oppositeProp = property.getOpposite();
            if (oppositeProp != null) {
                Iterator itemsIterator = items.iterator();
                while(itemsIterator.hasNext()) {
                    Object item = itemsIterator.next();
                    if (item != null) {
                        ((DataObject) item).set(oppositeProp, dataObject);
                        dataObject.set(oppositeProp, null);
                    }
                }
            }
        }

        // create new settings outside of updateContainment as we do earlier in currentElements.add
        updateSequence(property, items, updateSequence);

        return modified;
    }

    /**
     * Removes from this collection all of its currentElements that are contained in the specified collection.<br>
     * @param items
     * @return boolean
     */
    @Override
    public boolean removeAll(Collection items) {
        return removeAll(items, true);
    }

    /**
     * INTERNAL:
     * Removes from this collection all of its currentElements that are contained in the specified collection.<br>
     * @param items
     * @param updateSequence
     * @return
     */
    public boolean removeAll(Collection items, boolean updateSequence) {
        Iterator iter = items.iterator();
        boolean modified = false;
        while (iter.hasNext()) {
            Object next = iter.next();
            remove(next, false, updateSequence);
            modified = true;
        }
        return modified;
    }

    /**
     * Retains only the currentElements in this collection that are contained in the specified collection
     * (optional operation).<br>
     * In other words, removes from this collection all of its currentElements that
     * are not contained in the specified collection.<br>
     * @param itemsToKeep
     * @return boolean
     */
    @Override
    public boolean retainAll(Collection itemsToKeep) {
        // fail-fast range checking
        if (itemsToKeep == null) {
            return false;
        }

        if (itemsToKeep.size() == 0) {
            clear();
            return true;
        }

        boolean modified = false;

        // iterate across the full collection and remove only non-(itemsToKeep)
        // don't use an Iterator when modifying the list or we will
        // get a ConcurrentModificationException on the Iterator.
        int originalSize = size();// store: as size will reduce as we iterate
        int index = 0;

        // iterate all currentElements and update position only on skipped currentElements
        for (int original = 0; original < originalSize; original++) {
            // get object at current index
            Object anObject = get(index);

            // is this element in the keep list?
            if (!itemsToKeep.contains(anObject)) {
                remove(anObject);
                modified = true;
            } else {
                index++;
            }
        }

        // no delegation to superclass required
        return modified;
    }

    /**
     * Removes all of the currentElements from this list. The list will be empty after this call returns.
     */
    @Override
    public void clear() {
        clear(true);
    }

    /**
     * INTERNAL:
     * @param updateSequence
     */
    public void clear(boolean updateSequence) {
        // update element arrays before we modify original object
        int size = this.size();
        for (int i = size - 1; i >= 0; i--) {
            remove(i, updateSequence);
        }
    }

    /**
     * Replaces the element at the specified index in this list with the specified element.<br>
     * @param index
     * @param item
     * @return Object (the element previously at the specified position)
     */
    @Override
    public Object set(int index, Object item) {
        // fail-fast range checking
        if ((index < 0) || (index > size())) {
            throw new IndexOutOfBoundsException("index " + index + " is out of bounds.");
        }

        // delegate removal
        Object aPreviousObject = remove(index);

        // delegate insertion
        add(index, item);
        return aPreviousObject;
    }

    /**
     * INTERNAL:
     * Removes the element at the specified position in this list.<br>
     * Position index starts at 0.
     * @param index
     * @param updateSequence
     * @return Object (the element previously at the specified position)
     */
    public Object remove(int index, boolean updateSequence) {
        // fail-fast range checking
        if ((index < 0) || (index >= size())) {
            return null;
        }

        // update element arrays before we modify original object
        copyElements();

        /**
         * The order of operations for remove is
         * 1 - remove containment
         * 2 - remove elements
         *
         * This order is the reverse of the order in addAll
         * 1 - add elements
         * 2 - update containment
         */

        // Update containment of object and container, do not recursively remove containment
        int occurrence = getOccurrenceIndex(index);
        removeContainment(occurrence, currentElements.get(index), false, updateSequence);

        // delegate to superclass
        return currentElements.remove(index);
    }

    /**
     * INTERNAL:
     * Return the occurrence number for the current index in this list.
     * The return value will be non-zero when there are duplicates of an object instance.
     * <p>Example: occurrence number of index 1 = 0, of index 2 = 1</p>
     *     <p>[index]                              occurrence</p>
     *         <p>[0]    ItemImpl  (id=58)        0</p>
     *        <p>[1]    ItemImpl  (id=35)        0</p>
     *         <p>[2]    ItemImpl  (id=35)           1</p>
     *
     * @param index
     * @return
     */
    private int getOccurrenceIndex(int index) {
        // Assumption: no occurrences: return 0
        // Assumption: only 1 occurrence: return 0
        int occurrence = 0;
        boolean skipFirstOccurrence = true;
        Object targetObjectAtIndex = currentElements.get(index);
        for (int position = 0, size = size(); (position < size) && (position < (index + 1));
                 position++) {
            Object searchIndexObject = currentElements.get(position);

            // match only objects that are duplicates of this current one
            if (targetObjectAtIndex == searchIndexObject) {
                // skip counting the first occurrence
                if (skipFirstOccurrence) {
                    skipFirstOccurrence = false;
                } else {
                    occurrence++;
                }
            }
        }
        return occurrence;
    }

    /**
     * Removes the element at the specified position in this list.<br>
     * Position index starts at 0.
     * @param index
     * @return Object (the element previously at the specified position)
     */
    @Override
    public Object remove(int index) {
        return remove(index, true);
    }

    @Override
    public ListIterator listIterator() {
        return currentElements.listIterator();
    }

    @Override
    public ListIterator listIterator(int position) {
        return currentElements.listIterator(position);
    }

    /**
     * Return a view of the specified portion of the list
     * @param start - low endpoint (inclusive) of the subList.
     * @param end - high endpoint (exclusive) of the subList.
     * @return
     */
    @Override
    public List subList(int start, int end) {
        return currentElements.subList(start, end);
    }

    @Override
    public Object[] toArray() {
        return currentElements.toArray();
    }

    /**
     * Returns an array containing all of the currentElements in this list in proper sequence;
     *   the runtime type of the returned array is that of the specified array.
     *   Obeys the general contract of the Collection.toArray(Object[]) method.<br>
     * Specified by: toArray in interface {@literal Collection<E>}<br>
     *
     * Throws:<br>
     * ArrayStoreException - if the runtime type of the specified array is not a supertype of the
     *   runtime type of every element in this list.<br>
     * NullPointerException - if the specified array is null.<br>
     *
     * @param items -the array into which the currentElements of this list are to be stored, if it is big enough;
     *   otherwise, a new array of the same runtime type is allocated for this purpose.<br>
     * @return Object[] - an array containing the currentElements of this list.
     */
    @Override
    public Object[] toArray(Object[] items) {
        return currentElements.toArray(items);
    }

    @Override
    public int size() {
        return currentElements.size();
    }

    @Override
    public boolean isEmpty() {
        return currentElements.isEmpty();
    }

    @Override
    public boolean contains(Object item) {
        return currentElements.contains(item);
    }

    @Override
    public boolean containsAll(Collection items) {
        return currentElements.containsAll(items);
    }

    @Override
    public Iterator iterator() {
        return currentElements.iterator();
    }

    @Override
    public int indexOf(Object item) {
        return currentElements.indexOf(item);
    }

    @Override
    public int lastIndexOf(Object item) {
        return currentElements.lastIndexOf(item);
    }

    @Override
    public Object get(int position) {
        try {
            return currentElements.get(position);
        } catch (Exception e) {
            // Return null in case of exception, as per SDO 2.1 Spec
            return null;
        }
    }

    /**
     * INTERNAL:
     * Defined in SDO 2.01 spec on page 65 Externalizable function is called by
     * ObjectStream.writeObject() A replacement object for serialization can be
     * called here.
     * <p>Security Note:
     *     This public function exposes a data replacement vulnerability where an outside client
     *     can gain access and modify their non-final constants.
     *     We may need to wrap the GZIP streams in some sort of encryption when we are not
     *     using HTTPS or SSL/TLS on the wire.
     *
     * @see org.eclipse.persistence.sdo.SDOResolvable
     */
    public Object writeReplace() {
        return currentElements;
    }

    /**
     * INTERNAL:
     * @return
     */
    public List getCurrentElements() {
        return currentElements;
    }

    /**
     * INTERNAL:
     * bypass containment and changesummary copy of element list on modifications
     *
     */
    public void setCurrentElements(List currentElementsList) {
        currentElements = currentElementsList;
    }

    /**
     * Clone the ListWrapper.
     * This creates a new ListWrapper with the same contents as the original (shallow clone)
     * Minimal clone operation implemented to support usage in JPA
     */
    @Override
    public Object clone() {
        ListWrapper listWrapperClone = new ListWrapper(dataObject, property);
        listWrapperClone.setCurrentElements(new ArrayList(currentElements));
        return listWrapperClone;
    }
}
