/*
 * 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.internal.sessions;

import java.io.*;
import java.util.*;

import org.eclipse.persistence.internal.core.sessions.CoreAbstractRecord;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.sessions.Record;
import org.eclipse.persistence.internal.helper.DatabaseField;

/**
 * <p>
 * <b>Purpose</b>: Define the abstract definition of a record for internal use.
 * Public API should reference the Map or Record interface.
 * Subclasses are DatabaseRecord and XMLRecord.
 * <p>
 * <b>Responsibilities</b>: <ul>
 *      <li> Implement the Record and Map interfaces.
 * </ul>
 * @see DatabaseField
 */
public abstract class AbstractRecord extends CoreAbstractRecord implements Record, Cloneable, Serializable, Map {

    /** Use vector to store the fields/values for optimal performance.*/
    protected Vector<DatabaseField> fields;

    /** Use vector to store the fields/values for optimal performance.*/
    protected Vector values;

    /** Optimize field creation for field name lookup. */
    protected DatabaseField lookupField;

    /** PERF: Cache the row size. */
    protected int size;

    /** INTERNAL: indicator showing that no entry exists for a given key. */
    public static final AbstractRecord.NoEntry noEntry = new AbstractRecord.NoEntry();

    /** INTERNAL: flag for any database field containing a null value */
    protected boolean nullValueInFields;

    /** INTERNAL: SerializedObjectPolicy support */
    protected transient Object sopObject;

    /**
     * INTERNAL:
     * NoEntry: This is used to differentiate between the two kinds
     * of nulls: no entry exists, and the field is actually mapped
     * to null.
     */
    public static class NoEntry {
        private NoEntry() {
        }
    }

    /**
     * INTERNAL:
     *  converts JDBC results to collections of rows.
     */
    protected AbstractRecord() {
        this.fields = new NonSynchronizedVector();
        this.values = new NonSynchronizedVector();
        this.size = 0;
        this.nullValueInFields = false;
    }

    /**
     * INTERNAL:
     *  converts JDBC results to collections of rows.
     */
    protected AbstractRecord(int initialCapacity) {
        this.fields = new NonSynchronizedVector(initialCapacity);
        this.values = new NonSynchronizedVector(initialCapacity);
        this.size = 0;
        this.nullValueInFields = false;
    }

    /**
     * INTERNAL:
     *  converts JDBC results to collections of rows.
     */
    protected AbstractRecord(Vector fields, Vector values) {
        this.fields = fields;
        this.values = values;
        this.nullValueInFields = false;
        resetSize();
    }

    /**
     * INTERNAL:
     *  converts JDBC results to collections of rows.
     */
    protected AbstractRecord(Vector fields, Vector values, int size) {
        this.fields = fields;
        this.values = values;
        this.nullValueInFields = false;
        this.size = size;
    }

    /**
     * Reset the row size.
     * This must be reset after any change to the row.
     */
    protected void resetSize() {
        if (this.fields == null) {
            this.size = 0;
        } else {
            this.size = this.fields.size();
        }
    }

    /**
     * INTERNAL:
     * Add the field-value pair to the row.  Will not check,
     * will simply add to the end of the row
     */
    public void add(DatabaseField key, Object value) {
        this.fields.add(key);
        this.values.add(value);
        this.size++;
    }

    /**
     * PUBLIC:
     * Clear the contents of the row.
     */
    @Override
    public void clear() {
        this.fields = new Vector();
        this.values = new Vector();
        resetSize();
    }

    /**
     * INTERNAL:
     * Clone the row and its values.
     */
    @Override
    public AbstractRecord clone() {
        try {
            AbstractRecord clone = (AbstractRecord)super.clone();
            clone.fields = (Vector)this.fields.clone();
            clone.values = (Vector)this.values.clone();
            return clone;
        } catch (CloneNotSupportedException exception) {
            throw new InternalError();
        }
    }

    /**
     * PUBLIC:
     * Check if the value is contained in the row.
     */
    public boolean contains(Object value) {
        return containsValue(value);
    }

    /**
     * PUBLIC:
     * Check if the field is contained in the row.
     * Conform to hashtable interface.
     */
    @Override
    public boolean containsKey(Object key) {
        if (key instanceof String) {
            return containsKey((String)key);
        }
        if (key instanceof DatabaseField) {
            return containsKey((DatabaseField)key);
        }

        return false;
    }

    /**
     * PUBLIC:
     * Check if the field is contained in the row.
     */
    public boolean containsKey(String fieldName) {
        return containsKey(getLookupField(fieldName));
    }

    /**
     * INTERNAL:
     * Check if the field is contained in the row.
     */
    public boolean containsKey(DatabaseField key) {
        // Optimize check.
        int index = key.index;
        if ((index >= 0) && (index < this.size)) {
            DatabaseField field = this.fields.get(index);
            if ((field == key) || field.equals(key)) {
                return true;
            }
        }
        return this.fields.contains(key);
    }

    /**
     * PUBLIC:
     * Check if the value is contained in the row.
     */
    @Override
    public boolean containsValue(Object value) {
        return getValues().contains(value);
    }

    /**
     * PUBLIC:
     * Returns an Enumeration of the values.
     */
    public Enumeration elements() {
        return getValues().elements();
    }

    /**
     * PUBLIC:
     * Returns a set of the keys.
     */
    @Override
    public Set entrySet() {
        return new EntrySet();
    }

    /**
     * PUBLIC:
     * Retrieve the value for the field name.
     * A field is constructed on the name to check the hash table.
     * If missing null is returned.
     */
    @Override
    public Object get(Object key) {
        if (key instanceof String) {
            return get((String)key);
        } else if (key instanceof DatabaseField) {
            return get((DatabaseField)key);
        }
        return null;
    }

    /**
     * PUBLIC:
     * Retrieve the value for the field name.
     * A field is constructed on the name to check the hash table.
     * If missing null is returned.
     */
    public Object get(String fieldName) {
        return get(getLookupField(fieldName));
    }

    /**
     * Internal: factored out of getIndicatingNoEntry(String) to reduce complexity and have
     * get(string) use get(DatabaseField) instead of getIndicatingNoEntry and then doing an extra check
     */
    protected DatabaseField getLookupField(String fieldName){
        if (this.lookupField == null) {
            this.lookupField = new DatabaseField(fieldName);
        } else {
            this.lookupField.resetQualifiedName(fieldName);
        }
        return this.lookupField;
    }

    /**
     * PUBLIC:
     * Retrieve the value for the field name.
     * A field is constructed on the name to check the hash table.
     * If missing DatabaseRow.noEntry is returned.
     */
    public Object getIndicatingNoEntry(String fieldName) {
        // Optimized the field creation.
        return getIndicatingNoEntry(getLookupField(fieldName));
    }

    /**
     * INTERNAL:
     * Retrieve the value for the field. If missing null is returned.
     */
    public Object get(DatabaseField key) {
        // PERF: Direct variable access.
        // ** Code duplicated in getIndicatingNoEntry, replaceAt ensure kept in synch **
        // Optimize check.
        int index = key.index;
        if ((index >= 0) && (index < this.size)) {
            DatabaseField field = this.fields.get(index);
            if ((field == key) || field.equals(key)) {
                return this.values.get(index);
            }
        }
        int fieldsIndex = this.fields.indexOf(key);
        if (fieldsIndex >= 0) {
            // PERF: If the fields index was not set, then set it.
            if (index == -1) {
                key.setIndex(fieldsIndex);
            }
            return this.values.get(fieldsIndex);
        } else {
            return null;
        }
    }

    //----------------------------------------------------------------------------//
    public Object getValues(DatabaseField key) {
        return get(key);
    }

    public Object getValues(String key) {
        return get(key);
    }

    //----------------------------------------------------------------------------//

    /**
     * INTERNAL:
     * Retrieve the value for the field. If missing DatabaseRow.noEntry is returned.
     */
    public Object getIndicatingNoEntry(DatabaseField key) {
        // PERF: Direct variable access.
        // ** Code duplicated in get, ensure kept in synch **
        // Optimize check.
        int index = key.index;
        if ((index >= 0) && (index < this.size)) {
            DatabaseField field = this.fields.get(index);
            if ((field == key) || field.equals(key)) {
                return this.values.get(index);
            }
        }
        int fieldsIndex = this.fields.indexOf(key);
        if (fieldsIndex >= 0) {
            // PERF: If the fields index was not set, then set it.
            if (index == -1) {
                key.setIndex(fieldsIndex);
            }
            return this.values.get(fieldsIndex);
        } else {
            return AbstractRecord.noEntry;
        }
    }

    /**
     * INTERNAL:
     * Returns the row's field with the same name.
     */
    public DatabaseField getField(DatabaseField key) {
        // Optimize check.
        int index = key.index;
        if ((index >= 0) && (index < getFields().size())) {
            DatabaseField field = getFields().elementAt(index);
            if ((field == key) || field.equals(key)) {
                return field;
            }
        }
        for (index = 0; index < getFields().size(); index++) {
            DatabaseField field = getFields().elementAt(index);
            if ((field == key) || field.equals(key)) {
                return field;
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     */
    public Vector<DatabaseField> getFields() {
        return fields;
    }

    /**
     * INTERNAL:
     */
    public Vector getValues() {
        return values;
    }

    /**
     * PUBLIC:
     * Return if the row is empty.
     */
    @Override
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * INTERNAL:
     * Return true if the AbstractRecord has been marked as valid
     * to check the update call cache with, false otherwise.
     */
    public boolean hasNullValueInFields() {
        return this.nullValueInFields;
    }

    /**
     * PUBLIC:
     * Returns an Enumeration of the DatabaseField objects.
     */
    public Enumeration keys() {
        return getFields().elements();
    }

    /**
     * PUBLIC:
     * Returns a set of the keys.
     */
    @Override
    public Set keySet() {
        return new KeySet();
    }

    /**
     * Defines the virtual keySet.
     */
    protected class KeySet extends EntrySet {
        /**
         * Default constructor.
         */
        public KeySet() {
        }

        @Override
        public Iterator iterator() {
            return new RecordKeyIterator();
        }
        @Override
        public boolean contains(Object object) {
            return AbstractRecord.this.containsKey(object);
        }
        @Override
        public boolean remove(Object object) {
            return AbstractRecord.this.remove(object) != null;
        }
    }

    /**
     * Defines the virtual valuesSet.
     */
    protected class ValuesSet extends EntrySet {
        /**
         * Default constructor.
         */
        public ValuesSet() {
        }

        @Override
        public Iterator iterator() {
            return new RecordValuesIterator();
        }
        @Override
        public boolean contains(Object object) {
            return AbstractRecord.this.contains(object);
        }
        @Override
        public boolean remove(Object object) {
            int index = getValues().indexOf(object);
            if (index == -1) {
                return false;
            }
            AbstractRecord.this.remove(getFields().get(index));
            return true;
        }
    }

    /**
     * Defines the virtual entrySet.
     */
    protected class EntrySet extends AbstractSet {
        /**
         * Default constructor.
         */
        public EntrySet() {
            super();
        }

        @Override
        public Iterator iterator() {
            return new RecordEntryIterator();
        }
        @Override
        public int size() {
            return AbstractRecord.this.size();
        }
        @Override
        public boolean contains(Object object) {
            if (!(object instanceof Entry)) {
                return false;
            }
            return AbstractRecord.this.containsKey(((Entry)object).getKey());
        }
        @Override
        public boolean remove(Object object) {
            if (!(object instanceof Entry)) {
                return false;
            }
            AbstractRecord.this.remove(((Entry)object).getKey());
            return true;
        }
        @Override
        public void clear() {
            AbstractRecord.this.clear();
        }
    }

    /**
     * Defines the virtual entrySet iterator.
     */
    protected class RecordEntryIterator implements Iterator {
        int index;

        RecordEntryIterator() {
            this.index = 0;
        }

        @Override
        public boolean hasNext() {
            return this.index < AbstractRecord.this.size();
        }

        @Override
        public Object next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            this.index++;
            return new RecordEntry(getFields().get(this.index - 1), getValues().get(this.index - 1));
        }

        @Override
        public void remove() {
            if (this.index >= AbstractRecord.this.size()) {
                throw new IllegalStateException();
            }
            AbstractRecord.this.remove(getFields().get(this.index));
        }
    }

    /**
     * Defines the virtual keySet iterator.
     */
    protected class RecordKeyIterator extends RecordEntryIterator {
        /**
         * Default constructor.
         */
        public RecordKeyIterator() {
        }

        @Override
        public Object next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            this.index++;
            return getFields().get(this.index - 1);
        }
    }

    /**
     * Defines the virtual valuesSet iterator.
     */
    protected class RecordValuesIterator extends RecordEntryIterator {
        /**
         * Default constructor.
         */
        public RecordValuesIterator() {
        }

        @Override
        public Object next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            this.index++;
            return getValues().get(this.index - 1);
        }
    }

    /**
     * Entry class for implementing Map interface.
     */
    protected static class RecordEntry implements Entry {
    Object key;
    Object value;

    public RecordEntry(Object key, Object value) {
        this.key = key;
            this.value = value;
    }

    @Override
    public Object getKey() {
        return key;
    }

    @Override
    public Object getValue() {
        return value;
    }

    @Override
    public Object setValue(Object value) {
        Object oldValue = this.value;
        this.value = value;
        return oldValue;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Map.Entry)) {
        return false;
            }
        Map.Entry entry = (Map.Entry)object;
        return compare(key, entry.getKey()) && compare(value, entry.getValue());
    }

    @Override
    public int hashCode() {
        return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
    }

    @Override
    public String toString() {
        return key + "=" + value;
    }

        private boolean compare(Object object1, Object object2) {
            return (object1 == null ? object2 == null : object1.equals(object2));
        }
    }

    /**
     * INTERNAL:
     * Merge the provided row into this row.  Existing field values in this row will
     * be replaced with values from the provided row. Fields not in this row will be
     * added from provided row.  Values not in provided row will remain in this row.
     */

    public void mergeFrom(AbstractRecord row){
        for (int index = 0; index < row.size(); ++index){
            this.put(row.getFields().get(index), row.getValues().get(index));
        }
    }

    /**
     * PUBLIC:
     * Add the field-value pair to the row.
     */
    @Override
    public Object put(Object key, Object value) throws ValidationException {
        if (key instanceof String) {
            return put((String)key, value);
        } else if (key instanceof DatabaseField) {
            return put((DatabaseField)key, value);
        } else {
            throw ValidationException.onlyFieldsAreValidKeysForDatabaseRows();
        }
    }

    /**
     * PUBLIC:
     * Add the field-value pair to the row.
     */
    public Object put(String key, Object value) {
        return put(new DatabaseField(key), value);
    }

    /**
     * INTERNAL:
     * Add the field-value pair to the row.
     */
    public Object put(DatabaseField key, Object value) {
        int index = this.fields.indexOf(key);
        if (index >= 0) {
            return this.values.set(index, value);
        } else {
            add(key, value);
        }

        return null;
    }

    /**
     * PUBLIC:
     * Add all of the elements.
     */
    @Override
    public void putAll(Map map) {
        Iterator entriesIterator = map.entrySet().iterator();
        while (entriesIterator.hasNext()) {
            Map.Entry entry = (Map.Entry)entriesIterator.next();
            put(entry.getKey(), entry.getValue());
        }
    }

    /**
     * INTERNAL:
     * Remove the field key from the row.
     */
    @Override
    public Object remove(Object key) {
        if (key instanceof String) {
            return remove((String)key);
        } else if (key instanceof DatabaseField) {
            return remove((DatabaseField)key);
        }
        return null;
    }

    /**
     * INTERNAL:
     * Remove the field key from the row.
     */
    public Object remove(String fieldName) {
        return remove(new DatabaseField(fieldName));
    }

    /**
     * INTERNAL:
     * Remove the field key from the row.
     */
    public Object remove(DatabaseField key) {
        int index = getFields().indexOf(key);
        if (index >= 0) {
            getFields().removeElementAt(index);
            Object value = getValues().elementAt(index);
            getValues().removeElementAt(index);
            resetSize();
            return value;
        }
        return null;
    }

    /**
     * INTERNAL:
     * replaces the value at index with value
     */
    public void replaceAt(Object value, int index) {
        this.values.set(index, value);
    }

    /**
     * INTERNAL:
     * replaces the value at field with value
     */
    public void replaceAt(Object value, DatabaseField key) {
        int index = key.index;
        if ((index >= 0) && (index < this.size)) {
            DatabaseField field = this.fields.get(index);
            if ((field == key) || field.equals(key)) {
                this.values.set(index, value);
            }
        }
        int fieldsIndex = this.fields.indexOf(key);
        if (fieldsIndex >= 0) {
            // PERF: If the fields index was not set, then set it.
            if (index == -1) {
                key.setIndex(fieldsIndex);
            }
            this.values.set(fieldsIndex, value);
        }
    }

    protected void setFields(Vector fields) {
        this.fields = fields;
        resetSize();
    }

    /**
     * INTERNAL:
     * Set the validForUpdateCallCacheCheck attribute to true if the row
     * does not contain nulls, false otherwise
     */
    public void setNullValueInFields(boolean nullValueInFields) {
        this.nullValueInFields = nullValueInFields;
    }

    protected void setValues(Vector values) {
        this.values = values;
    }

    /**
     * PUBLIC:
     * Return the number of field/value pairs in the row.
     */
    @Override
    public int size() {
        return this.fields.size();
    }

    /**
     * INTERNAL:
     */
    @Override
    public String toString() {
        StringWriter writer = new StringWriter();
        writer.write(Helper.getShortClassName(getClass()));
        writer.write("(");

        for (int index = 0; index < getFields().size(); index++) {
            writer.write(Helper.cr());
            writer.write("\t");
            writer.write(String.valueOf((getFields().elementAt(index))));
            writer.write(" => ");
            writer.write(String.valueOf((getValues().elementAt(index))));
        }
        if (this.sopObject != null) {
            writer.write(Helper.cr());
            writer.write(" sopObject = ");
            writer.write(this.sopObject.toString());
        }
        writer.write(")");

        return writer.toString();
    }

    /**
     * PUBLIC:
     * Returns an collection of the values.
     */
    @Override
    public Collection values() {
        return new ValuesSet();
    }

    /**
     * INTERNAL:
     */
    public boolean hasSopObject() {
        return this.sopObject != null;
    }

    /**
     * INTERNAL:
     */
    public Object getSopObject() {
        return this.sopObject;
    }

    /**
     * INTERNAL:
     */
    public void setSopObject(Object sopObject) {
        this.sopObject = sopObject;
    }
}
