package com.revolsys.record;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.revolsys.identifier.SingleIdentifier;
import com.revolsys.record.schema.FieldDefinition;
import com.revolsys.record.schema.RecordDefinition;
import com.revolsys.util.Property;
/**
* The ArrayRecord is an implementation of {@link Record} which uses an array of
* Objects as the storage for the field values.
*/
public class ArrayRecord extends BaseRecord {
public static final RecordFactory<ArrayRecord> FACTORY = ArrayRecord::newRecord;
/** Serialization version */
private static final long serialVersionUID = 1L;
/**
* Construct a new ArrayRecord using the record definition
*
* @param recordDefinition The record definition used to create the instance.
* @return The Record instance.
*/
public static ArrayRecord newRecord(final RecordDefinition recordDefinition) {
return new ArrayRecord(recordDefinition);
}
/** The object's field values. */
private Object[] values;
/**
* Construct a new ArrayRecord as a deep clone of the field values.
* Objects can only be cloned if they have a publicly accessible
* {@link #clone()} method.
*
* @param record The object to clone.
*/
public ArrayRecord(final Record record) {
this(record.getRecordDefinition(), record);
}
/**
* Construct a new empty ArrayRecord using the recordDefinition.
*
* @param recordDefinition The recordDefinition defining the object type.
*/
public ArrayRecord(final RecordDefinition recordDefinition) {
super(recordDefinition);
initDefaultValues(recordDefinition);
setState(RecordState.NEW);
}
public ArrayRecord(final RecordDefinition recordDefinition,
final Iterable<? extends Object> values) {
this(recordDefinition);
initDefaultValues(recordDefinition);
setValues(values);
setState(RecordState.NEW);
}
public ArrayRecord(final RecordDefinition recordDefinition,
final Map<String, ? extends Object> values) {
super(recordDefinition);
initDefaultValues(recordDefinition);
initValues(values);
setState(RecordState.NEW);
}
public ArrayRecord(final RecordDefinition recordDefinition, final Object[] values) {
this(recordDefinition);
initDefaultValues(recordDefinition);
setValues(values);
setState(RecordState.NEW);
}
/**
* Construct a new clone of the record.
*
* @return The cloned record.
*/
@Override
public ArrayRecord clone() {
final ArrayRecord clone = (ArrayRecord)super.clone();
clone.values = this.values.clone();
return clone;
}
/**
* Get the value of the field with the specified index.
*
* @param index The index of the field.
* @return The field value.
*/
@Override
@SuppressWarnings("unchecked")
public <T extends Object> T getValue(final int index) {
if (index < 0) {
return null;
} else {
return (T)this.values[index];
}
}
/**
* Get the values of all values.
*
* @return The field value.
*/
@Override
public List<Object> getValues() {
return Arrays.asList(this.values);
}
@Override
public int hashCode() {
return this.values.hashCode();
}
protected void initDefaultValues(final RecordDefinition recordDefinition) {
if (recordDefinition == null) {
this.values = new Object[0];
} else {
final int fieldCount = recordDefinition.getFieldCount();
this.values = new Object[fieldCount];
final Map<String, Object> defaultValues = recordDefinition.getDefaultValues();
setValuesByPath(defaultValues);
}
}
/**
* Set the value of the field with the specified name.
*
* @param index The index of the field.
* @param value The new value.
*/
@Override
protected boolean setValue(final FieldDefinition fieldDefinition, Object value) {
boolean updated = false;
if (value instanceof String) {
final String string = (String)value;
if (!Property.hasValue(string)) {
value = null;
}
}
if (value instanceof SingleIdentifier) {
final SingleIdentifier identifier = (SingleIdentifier)value;
value = identifier.getValue(0);
}
final Object newValue = fieldDefinition.toFieldValue(value);
final int index = fieldDefinition.getIndex();
final Object oldValue = this.values[index];
if (!fieldDefinition.equals(oldValue, newValue)) {
updated = true;
updateState();
fieldDefinition.equals(oldValue, newValue);
}
this.values[index] = newValue;
return updated;
}
}