package com.revolsys.swing.map.layer.record;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.revolsys.datatype.DataType;
import com.revolsys.identifier.Identifier;
import com.revolsys.io.BaseCloseable;
import com.revolsys.record.ArrayRecord;
import com.revolsys.record.RecordState;
import com.revolsys.record.schema.FieldDefinition;
import com.revolsys.record.schema.RecordDefinition;
public class ArrayLayerRecord extends ArrayRecord implements LayerRecord {
private static final Map<String, Object> EMPTY_ORIGINAL_VALUES = Collections.emptyMap();
private static final long serialVersionUID = 1L;
private Identifier identifier;
private final AbstractRecordLayer layer;
private Map<String, Object> originalValues = EMPTY_ORIGINAL_VALUES;
public ArrayLayerRecord(final AbstractRecordLayer layer) {
super(layer.getRecordDefinition());
this.layer = layer;
}
public ArrayLayerRecord(final AbstractRecordLayer layer,
final Map<String, ? extends Object> values) {
super(layer.getRecordDefinition());
setState(RecordState.INITIALIZING);
initValues(values);
setState(RecordState.PERSISTED);
this.layer = layer;
}
protected ArrayLayerRecord(final RecordStoreLayer layer,
final RecordDefinition recordDefinition) {
super(recordDefinition);
this.layer = layer;
}
/**
* Internal method to revert the records values to the original
*/
@Override
public final boolean cancelChanges() {
boolean cancelled = false;
synchronized (getSync()) {
final Map<String, Object> originalValues = this.originalValues;
RecordState state = getState();
final AbstractRecordLayer layer = getLayer();
try (
BaseCloseable disabled = layer.eventsDisabled()) {
if (originalValues != EMPTY_ORIGINAL_VALUES) {
setState(RecordState.INITIALIZING);
super.setValues(originalValues);
}
if (state == RecordState.MODIFIED || state == RecordState.DELETED) {
state = RecordState.PERSISTED;
cancelled = true;
}
} finally {
setState(state);
}
this.originalValues = EMPTY_ORIGINAL_VALUES;
}
if (cancelled) {
firePropertyChange(EVENT_RECORD_CHANGED, false, true);
}
return cancelled;
}
@Override
public void clearChanges() {
synchronized (getSync()) {
final RecordState state = getState();
if (state == RecordState.PERSISTED) {
this.originalValues = EMPTY_ORIGINAL_VALUES;
}
}
}
@Override
public Identifier getIdentifier() {
if (this.identifier == null) {
this.identifier = super.getIdentifier();
}
return this.identifier;
}
@Override
public AbstractRecordLayer getLayer() {
return this.layer;
}
@Override
@SuppressWarnings("unchecked")
public <T> T getOriginalValue(final String name) {
synchronized (getSync()) {
final Map<String, Object> originalValues = this.originalValues;
if (originalValues.containsKey(name)) {
return (T)originalValues.get(name);
}
return (T)getValue(name);
}
}
protected Object getSync() {
if (this.layer == null) {
return new Object();
} else {
return this.layer.getSync();
}
}
protected boolean isHasOriginalValues() {
return !this.originalValues.isEmpty();
}
@Override
public boolean isModified(final String fieldName) {
synchronized (getSync()) {
final Map<String, Object> originalValues = this.originalValues;
if (originalValues == null) {
return false;
} else {
return originalValues.containsKey(fieldName);
}
}
}
@Override
public LayerRecord revertChanges() {
if (cancelChanges()) {
final AbstractRecordLayer layer = getLayer();
layer.revertChanges(this);
firePropertyChange("state", RecordState.MODIFIED, RecordState.PERSISTED);
}
return this;
}
@Override
protected boolean setValue(final FieldDefinition fieldDefinition, final Object value) {
synchronized (getSync()) {
boolean updated = false;
final int fieldIndex = fieldDefinition.getIndex();
final String fieldName = fieldDefinition.getName();
final Object newValue = fieldDefinition.toFieldValue(value);
final Object oldValue = getValue(fieldIndex);
RecordState newState = null;
if (!DataType.equal(oldValue, newValue)) {
final AbstractRecordLayer layer = getLayer();
final RecordState state = getState();
switch (state) {
case INITIALIZING:
// Allow modification on initialization
break;
case NEW:
if (!layer.isCanAddRecords()) {
throw new IllegalStateException(
"Adding new records is not supported for layer " + layer);
}
break;
case DELETED:
throw new IllegalStateException("Cannot edit a deleted record for layer " + layer);
case PERSISTED:
case MODIFIED:
if (layer.isCanEditRecords()) {
final Object originalValue = getOriginalValue(fieldName);
Map<String, Object> originalValues = this.originalValues;
synchronized (originalValues) {
if (fieldDefinition.equals(originalValue, newValue)) {
if (originalValues != EMPTY_ORIGINAL_VALUES) {
originalValues.remove(fieldName);
if (originalValues.isEmpty()) {
originalValues = EMPTY_ORIGINAL_VALUES;
newState = RecordState.PERSISTED;
}
}
} else {
if (originalValues == EMPTY_ORIGINAL_VALUES) {
originalValues = new HashMap<>();
}
originalValues.put(fieldName, originalValue);
if (RecordState.INITIALIZING != state) {
newState = RecordState.MODIFIED;
}
}
this.originalValues = originalValues;
}
} else {
throw new IllegalStateException(
"Editing records is not supported for layer " + layer);
}
break;
}
updated |= super.setValue(fieldDefinition, newValue);
if (newState != null) {
setState(newState);
}
if (state != RecordState.INITIALIZING) {
firePropertyChange(fieldName, oldValue, newValue);
layer.updateRecordState(this);
}
}
return updated;
}
}
}