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

/**
 * <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 DataRecord, 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;
    }
}
