All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.teamapps.universaldb.pojo.AbstractUdbEntity Maven / Gradle / Ivy

There is a newer version: 0.6.20
Show newest version
/*-
 * ========================LICENSE_START=================================
 * UniversalDB
 * ---
 * Copyright (C) 2014 - 2023 TeamApps.org
 * ---
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================LICENSE_END==================================
 */
package org.teamapps.universaldb.pojo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.teamapps.universaldb.UniversalDB;
import org.teamapps.universaldb.context.UserContext;
import org.teamapps.universaldb.index.FieldIndex;
import org.teamapps.universaldb.index.SortEntry;
import org.teamapps.universaldb.index.TableIndex;
import org.teamapps.universaldb.index.bool.BooleanIndex;
import org.teamapps.universaldb.index.file.FileValue;
import org.teamapps.universaldb.index.file.store.FileStore;
import org.teamapps.universaldb.index.numeric.*;
import org.teamapps.universaldb.index.reference.multi.MultiReferenceIndex;
import org.teamapps.universaldb.index.reference.single.SingleReferenceIndex;
import org.teamapps.universaldb.index.reference.value.*;
import org.teamapps.universaldb.index.text.TextIndex;
import org.teamapps.universaldb.index.transaction.request.TransactionRequest;
import org.teamapps.universaldb.index.transaction.request.TransactionRequestRecord;
import org.teamapps.universaldb.index.transaction.request.TransactionRequestRecordValue;
import org.teamapps.universaldb.index.translation.TranslatableText;
import org.teamapps.universaldb.index.translation.TranslatableTextIndex;
import org.teamapps.universaldb.index.versioning.RecordUpdate;
import org.teamapps.universaldb.record.EntityBuilder;
import org.teamapps.universaldb.schema.Table;

import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public abstract class AbstractUdbEntity implements Entity, EntityBuilder {

	private static final Logger log = LoggerFactory.getLogger(AbstractUdbEntity.class);
	private static final AtomicInteger correlationIdGenerator = new AtomicInteger();
	private static final int MAX_CORRELATION_ID = 2_000_000_000;

	private final TableIndex tableIndex;
	private int id;
	private boolean createEntity;
	private int correlationId;
	private EntityChangeSet entityChangeSet;
	private TransactionRequest transactionRequest;

	public static  List createEntityList(EntityBuilder entityBuilder, List recordIds){
		List list = new ArrayList<>();
		for (Integer recordId : recordIds) {
			list.add(entityBuilder.build(recordId));
		}
		return list;
	}

	public static FileValue createFileValue(File file) {
		return createFileValue(file, null);
	}

	public static FileValue createFileValue(File file, String fileName) {
		return file != null ? FileValue.create(file, fileName) : null;
	}


	public static  List sort(TableIndex table, List list, String sortFieldName, boolean ascending, UserContext userContext, String ... path) {
		SingleReferenceIndex[] referencePath = getReferenceIndices(table, path);
		FieldIndex column = getSortColumn(table, sortFieldName, referencePath);
		if (column == null) {
			return list;
		}
		List> sortEntries = SortEntry.createSortEntries(list, referencePath);
		sortEntries = column.sortRecords(sortEntries, ascending, userContext);
		return sortEntries.stream().map(SortEntry::getEntity).collect(Collectors.toList());
	}

	public static  List sort(TableIndex table, EntityBuilder builder, BitSet recordIds, String sortFieldName, boolean ascending, UserContext userContext, String ... path) {
		SingleReferenceIndex[] referencePath = getReferenceIndices(table, path);
		FieldIndex column = getSortColumn(table, sortFieldName, referencePath);
		if (column == null) {
			return createUnsortedList(recordIds, builder);
		}
		List sortEntries = SortEntry.createSortEntries(recordIds, referencePath);
		sortEntries = column.sortRecords(sortEntries, ascending, userContext);
		List list = new ArrayList<>();
		for (SortEntry entry : sortEntries) {
			list.add(builder.build(entry.getId()));
		}
		return list;
	}

	private static  List createUnsortedList(BitSet records, EntityBuilder builder) {
		List list = new ArrayList<>();
		for (int id = records.nextSetBit(0); id >= 0; id = records.nextSetBit(id + 1)) {
			list.add(builder.build(id));
		}
		return list;
	}

	private static SingleReferenceIndex[] getReferenceIndices(TableIndex table, String[] path) {
		SingleReferenceIndex[] referencePath = null;
		if (path != null && path.length > 0) {
			referencePath = new SingleReferenceIndex[path.length];
			TableIndex pathTable = table;
			for (int i = 0; i < path.length; i++) {
				referencePath[i] = (SingleReferenceIndex) pathTable.getFieldIndex(path[i]);
				pathTable = referencePath[i].getReferencedTable();
			}
		}
		return referencePath;
	}

	private static FieldIndex getSortColumn(TableIndex table, String sortFieldName, SingleReferenceIndex[] referencePath) {
		FieldIndex column;
		if (referencePath != null && referencePath.length > 0) {
			column = referencePath[referencePath.length - 1].getReferencedTable().getFieldIndex(sortFieldName);
		} else {
			column = table.getFieldIndex(sortFieldName);
		}
		return column;
	}

	public AbstractUdbEntity(TableIndex tableIndex) {
		this.tableIndex = tableIndex;
		createEntity = true;
		createCorrelationId();
	}

	public AbstractUdbEntity(TableIndex tableIndex, int id, boolean createEntity) {
		this.tableIndex = tableIndex;
		this.id = id;
		this.createEntity = createEntity;
		if (createEntity) {
			createCorrelationId();
		}
	}

	private void createCorrelationId() {
		if (correlationId > 0) {
			return;
		}
		correlationId = correlationIdGenerator.incrementAndGet();
		if (correlationId == MAX_CORRELATION_ID) {
			correlationIdGenerator.set(0);
		}
	}

	@Override
	public int getId() {
		if (id == 0 && transactionRequest != null) {
			id = transactionRequest.getResolvedRecordIdByCorrelationId(correlationId);
		}
		return id;
	}

	@Override
	public String getTable() {
		return tableIndex.getName();
	}

	@Override
	public String getDatabase() {
		return tableIndex.getDatabaseIndex().getName();
	}

	public int createdBy() {
		FieldIndex fieldIndex = tableIndex.getFieldIndex(Table.FIELD_CREATED_BY);
		return fieldIndex != null ? getIntValue((IntegerIndex) fieldIndex) : 0;
	}



	public List getRecordUpdates() {
		try {
			return tableIndex.getRecordVersioningIndex().readRecordUpdates(id);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	protected int getCorrelationId() {
		return correlationId;
	}

	public Object getEntityValue(String fieldName) {
		if (Table.FIELD_ID.equals(fieldName)) {
			return getId();
		}
		FieldIndex index = tableIndex.getFieldIndex(fieldName);
		if (index != null) {
			return index.getGenericValue(getId());
		} else {
			return null;
		}
	}

	public void setEntityValue(String fieldName, Object value) {
		FieldIndex index = tableIndex.getFieldIndex(fieldName);
		if (index != null) {
			setChangeValue(index, value, null);
		}
	}

	protected void setChangeValue(FieldIndex index, Object value, TableIndex tableIndex) {
		checkChangeSet();
		entityChangeSet.addChangeValue(index, value);
	}

	protected void setSingleReferenceValue(SingleReferenceIndex index, Entity reference, TableIndex tableIndex) {
		AbstractUdbEntity entity = (AbstractUdbEntity) reference;
		RecordReference recordReference = null;
		if (entity != null) {
			recordReference = new RecordReference(entity.getId(), entity.getCorrelationId());
		}
		int currentValue = index.getValue(getId());
		if ((currentValue == 0 && entity != null) || (currentValue > 0 && entity == null) || (entity != null && (entity.getId() == 0 || entity.getId() != currentValue))) {
			checkChangeSet();
			entityChangeSet.addChangeValue(index, recordReference);
			entityChangeSet.setReferenceChange(index, entity);
		}
	}

	protected  List createEntityList(FieldIndex index, EntityBuilder entityBuilder) {
		TransactionRequestRecordValue changeValue = getChangeValue(index);
		MultiReferenceEditValue editValue = (MultiReferenceEditValue) changeValue.getValue();
		MultiReferenceIndex multiReferenceIndex = (MultiReferenceIndex) index;
		return createEntityList(editValue, multiReferenceIndex.getReferencesAsList(id), entityBuilder);
	}

	protected  List createEntityList(MultiReferenceEditValue editValue, List referencedRecords, EntityBuilder entityBuilder) {
		Map entityByReference = (Map) entityChangeSet.getEntityByReference();
		List list = new ArrayList<>();
		if (!editValue.getSetReferences().isEmpty() || editValue.isRemoveAll()) {
			List references = editValue.isRemoveAll() ? editValue.getAddReferences() : editValue.getSetReferences();
			references.forEach(reference -> {
				OTHER_ENTITY entity = entityByReference.get(reference);
				if (entity == null && reference.getRecordId() > 0) {
					entity = entityBuilder.build(reference.getRecordId());
				}
				if (entity != null) {
					list.add(entity);
				} else {
					log.error("Cannot add reference to list: no record id and no matching correlation id!");
				}
			});
			return list;
		} else {
			Set removeSet = new HashSet<>();
			editValue.getRemoveReferences().forEach(reference -> {
				if (reference.getRecordId() > 0) {
					removeSet.add(reference.getRecordId());
				} else {
					OTHER_ENTITY entity = entityByReference.get(reference);
					if (entity != null) {
						removeSet.add(entity.getId());
					}
				}
			});
			List addEntities = new ArrayList<>();
			editValue.getAddReferences().forEach(reference -> {
				OTHER_ENTITY entity = entityByReference.get(reference);
				if (entity == null && reference.getRecordId() > 0) {
					entity = entityBuilder.build(reference.getRecordId());
				}
				if (entity != null) {
					addEntities.add(entity);
				}
			});
			Set addEntitySet = new HashSet<>();
			addEntities.forEach(entity -> addEntitySet.add(entity.getId()));
			for (Integer recordId : referencedRecords) {
				if (!removeSet.contains(recordId) && !addEntitySet.contains(recordId)) {
					list.add(entityBuilder.build(recordId));
				}
			}
			list.addAll(addEntities);
			return list;
		}
	}

	protected TransactionRequestRecordValue getChangeValue(FieldIndex index) {
		if (entityChangeSet == null) {
			return null;
		} else {
			return entityChangeSet.getChangeValue(index);
		}
	}

	protected Object getChangedValue(FieldIndex index) {
		if (entityChangeSet == null) {
			return null;
		} else {
			return entityChangeSet.getChangeValue(index).getValue();
		}
	}

	protected AbstractUdbEntity getReferenceChangeValue(FieldIndex index) {
		if (entityChangeSet == null) {
			return null;
		} else {
			return entityChangeSet.getReferenceChange(index.getMappingId());
		}
	}

	protected void addMultiReferenceValue(List entities, MultiReferenceIndex multiReferenceIndex) {
		if (entities == null || entities.isEmpty()) {
			return;
		}
		MultiReferenceEditValue editValue = getOrCreateMultiReferenceEditValue(multiReferenceIndex);
		List references = createRecordReferences(entities);

		editValue.addReferences(references);
	}

	protected void removeMultiReferenceValue(List entities, MultiReferenceIndex multiReferenceIndex) {
		if (entities == null || entities.isEmpty()) {
			return;
		}
		MultiReferenceEditValue editValue = getOrCreateMultiReferenceEditValue(multiReferenceIndex);
		List references = createRecordReferences(entities);
		editValue.removeReferences(references);
	}

	protected void setMultiReferenceValue(List entities, MultiReferenceIndex multiReferenceIndex) {
		if (entities == null || entities.isEmpty()) {
			if (getChangeValue(multiReferenceIndex) != null || !multiReferenceIndex.isEmpty(getId())) {
				removeAllMultiReferenceValue(multiReferenceIndex);
			}
		} else {
			if (getChangeValue(multiReferenceIndex) == null && multiReferenceIndex.getReferencesCount(getId()) == entities.size() && entities.stream().allMatch(Entity::isStored)) {
				Set entityIdSet = entities.stream().map(Entity::getId).collect(Collectors.toSet());
				if (entityIdSet.containsAll(multiReferenceIndex.getReferencesAsList(getId()))) {
					return;
				}
			}
			MultiReferenceEditValue editValue = getOrCreateMultiReferenceEditValue(multiReferenceIndex);
			List references = createRecordReferences(entities);
			editValue.setReferences(references);
		}
	}

	protected void removeAllMultiReferenceValue(MultiReferenceIndex multiReferenceIndex) {
		MultiReferenceEditValue editValue = getOrCreateMultiReferenceEditValue(multiReferenceIndex);
		editValue.setRemoveAll();
	}

	private List createRecordReferences(List entities) {
		List references = new ArrayList<>();
		for (Entity entity : entities) {
			AbstractUdbEntity udbEntity = (AbstractUdbEntity) entity;
			RecordReference recordReference = new RecordReference(udbEntity.getId(), udbEntity.getCorrelationId());
			references.add(recordReference);
			entityChangeSet.addRecordReference(recordReference, entity);
		}
		return references;
	}

	private MultiReferenceEditValue getOrCreateMultiReferenceEditValue(MultiReferenceIndex multiReferenceIndex) {
		MultiReferenceEditValue editValue;
		TransactionRequestRecordValue changeValue = getChangeValue(multiReferenceIndex);
		if (changeValue != null) {
			editValue = (MultiReferenceEditValue) changeValue.getValue();
		} else {
			editValue = new MultiReferenceEditValue();
			setChangeValue(multiReferenceIndex, editValue, tableIndex);
		}
		return editValue;
	}

	public boolean getBooleanValue(BooleanIndex index) {
		if (isChanged(index)) {
			return (boolean) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setBooleanValue(boolean value, BooleanIndex index) {
		if (getBooleanValue(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public short getShortValue(ShortIndex index) {
		if (isChanged(index)) {
			return (short) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setShortValue(short value, ShortIndex index) {
		if (getShortValue(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public int getIntValue(IntegerIndex index) {
		if (isChanged(index)) {
			return (int) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setIntValue(int value, IntegerIndex index) {
		if (getIntValue(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public long getLongValue(LongIndex index) {
		if (isChanged(index)) {
			return (long) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setLongValue(long value, LongIndex index) {
		if (getLongValue(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public float getFloatValue(FloatIndex index) {
		if (isChanged(index)) {
			return (float) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setFloatValue(float value, FloatIndex index) {
		if (getFloatValue(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public double getDoubleValue(DoubleIndex index) {
		if (isChanged(index)) {
			return (double) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setDoubleValue(double value, DoubleIndex index) {
		if (getDoubleValue(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public String getTextValue(TextIndex index) {
		if (isChanged(index)) {
			return (String) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setTextValue(String value, TextIndex index) {
		if (value != null && value.isEmpty()) {
			value = null;
		}
		if (!Objects.equals(getTextValue(index), value)) {
 			setChangeValue(index, value, tableIndex);
		}
	}

	public TranslatableText getTranslatableTextValue(TranslatableTextIndex index) {
		if (isChanged(index)) {
			return (TranslatableText) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setTranslatableTextValue(TranslatableText value, TranslatableTextIndex index) {
		setChangeValue(index, value, tableIndex);
	}

	public Instant getTimestampValue(IntegerIndex index) {
		int value;
		if (isChanged(index)) {
			value = (int) getChangedValue(index);
		} else {
			value = index.getValue(getId());
		}
		return value == 0 ? null : Instant.ofEpochSecond(value);
	}

	public int getTimestampAsEpochSecond(IntegerIndex index) {
		if (isChanged(index)) {
			return (int) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public long getTimestampAsEpochMilli(IntegerIndex index) {
		if (isChanged(index)) {
			return ((Integer) getChangedValue(index)).longValue() * 1000L;
		} else {
			return index.getValue(getId()) * 1000L;
		}
	}

	public void setTimestampValue(Instant value, IntegerIndex index) {
		if (!Objects.equals(getTimestampValue(index), value)) {
			Integer intValue = value != null ? (int) value.getEpochSecond() : 0;
			setChangeValue(index, intValue, tableIndex);
		}
	}

	public void setTimestampAsEpochSecond(int value, IntegerIndex index) {
		if (getTimestampAsEpochSecond(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public void setTimestampAsEpochMilli(long value, IntegerIndex index) {
		if (getTimestampAsEpochMilli(index) != value) {
			int intValue = (int) (value / 1000);
			setChangeValue(index, intValue, tableIndex);
		}
	}

	public Instant getTimeValue(IntegerIndex index) {
		int value;
		if (isChanged(index)) {
			value = (int) getChangedValue(index);
		} else {
			value = index.getValue(getId());
		}
		return value == 0 ? null: Instant.ofEpochSecond(value);
	}

	public void setTimeValue(Instant value, IntegerIndex index) {
		if (!Objects.equals(getTimeValue(index), value)) {
			Integer intValue = value != null ? (int) value.getEpochSecond() : 0;
			setChangeValue(index, intValue, tableIndex);
		}
	}

	public Instant getDateValue(LongIndex index) {
		long value;
		if (isChanged(index)) {
			value = (long) getChangedValue(index);
		} else {
			value = index.getValue(getId());
		}
		return value == 0 ? null : Instant.ofEpochMilli(value);
	}

	public long getDateAsEpochMilli(LongIndex index) {
		if (isChanged(index)) {
			return (long) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setDateValue(Instant value, LongIndex index) {
		if (!Objects.equals(getDateValue(index), value)) {
			Long longValue = value != null ? value.toEpochMilli() : 0;
			setChangeValue(index, longValue, tableIndex);
		}
	}

	public void setDateAsEpochMilli(long value, LongIndex index) {
		if (getDateAsEpochMilli(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public Instant getDateTimeValue(LongIndex index) {
		long value;
		if (isChanged(index)) {
			value = (long) getChangedValue(index);
		} else {
			value = index.getValue(getId());
		}
		return value == 0 ? null : Instant.ofEpochMilli(value);
	}

	public long getDateTimeAsEpochMilli(LongIndex index) {
		if (isChanged(index)) {
			return (long) getChangedValue(index);
		} else {
			return index.getValue(getId());
		}
	}

	public void setDateTimeValue(Instant value, LongIndex index) {
		if (!Objects.equals(getDateTimeValue(index), value)) {
			Long longValue = value != null ? (long) value.toEpochMilli() : 0;
			setChangeValue(index, longValue, tableIndex);
		}
	}

	public void setDateTimeAsEpochMilli(long value, LongIndex index) {
		if (getDateTimeAsEpochMilli(index) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public LocalDate getLocalDateValue(LongIndex index) {
		long value;
		if (isChanged(index)) {
			value = (long) getChangedValue(index);
		} else {
			value = index.getValue(getId());
		}
		return value == 0 ? null : LocalDate.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC);
	}

	public void setLocalDateValue(LocalDate value, LongIndex index) {
		long longValue = value != null ? value.atStartOfDay(ZoneOffset.UTC).toEpochSecond() * 1000L : 0;
		LocalDate currentValue = getLocalDateValue(index);
		if (!Objects.equals(currentValue, value) && (currentValue != null || longValue != 0)) {
			setChangeValue(index, longValue, tableIndex);
		}
	}

	public void setLocalDateAsEpochMilli(long value, LongIndex index) {
		if (index.getValue(getId()) != value) {
			setChangeValue(index, value, tableIndex);
		}
	}

	public > ENUM getEnumValue(ShortIndex index, ENUM[] values) {
		short shortValue;
		if (isChanged(index)) {
			shortValue = (short) getChangedValue(index);
		} else {
			shortValue = index.getValue(getId());
		}
		return shortValue == 0 ? null : values[shortValue - 1];
	}

	public > void setEnumValue(ShortIndex index, ENUM value) {
		short shortValue = (short) (value != null ? value.ordinal() + 1 : 0);
		if (getShortValue(index) != shortValue) {
			setChangeValue(index, shortValue, tableIndex);
		}
	}

	public  List getMultiReferenceValue(MultiReferenceIndex index, EntityBuilder entityBuilder) {
		if (isChanged(index)) {
			return createEntityList(index, entityBuilder);
		} else {
			if (!index.isEmpty(getId())) {
				return createEntityList(entityBuilder, index.getReferencesAsList(getId()));
			} else {
				return Collections.emptyList();
			}
		}
	}

	public  int getMultiReferenceValueCount(MultiReferenceIndex index, EntityBuilder entityBuilder) {
		if (isChanged(index)) {
			return createEntityList(index, entityBuilder).size();
		} else {
			return index.getReferencesCount(getId());
		}
	}

	public  BitSet getMultiReferenceValueAsBitSet(MultiReferenceIndex index, EntityBuilder entityBuilder) {
		if (isChanged(index)) {
			BitSet bitSet = new BitSet();
			createEntityList(index, entityBuilder).stream().map(Entity::getId).forEach(bitSet::set);
			return bitSet;
		} else {
			return index.getReferencesAsBitSet(getId());
		}
	}

	public boolean isChanged(FieldIndex index) {
		return entityChangeSet != null && entityChangeSet.isChanged(index);
	}

	@Override
	public void clearChanges() {
		entityChangeSet = null;
	}

	@Override
	public boolean isChanged(String fieldName) {
		return isChanged(tableIndex.getFieldIndex(fieldName));
	}

	@Override
	public void clearFieldChanges(String fieldName) {
		if (entityChangeSet != null) {
			entityChangeSet.removeChange(tableIndex.getFieldIndex(fieldName));
		}
	}

	@Override
	public boolean isModified() {
		return entityChangeSet != null;
	}

	private void checkChangeSet() {
		if (entityChangeSet == null) {
			entityChangeSet = new EntityChangeSet();
			createCorrelationId();
		}
	}



	public void saveRecord(UniversalDB database, int userId, long timestamp) {
		if (entityChangeSet != null) {
			this.transactionRequest = database.createTransactionRequest(userId, timestamp);
			saveRecord(transactionRequest, database);
			database.executeTransaction(transactionRequest);
			if (id == 0) {
				id = transactionRequest.getResolvedRecordIdByCorrelationId(correlationId);
			}
		}
	}

	public void saveRecord(UniversalDB database) {
		if (entityChangeSet != null) {
			this.transactionRequest = database.createTransactionRequest();
			saveRecord(transactionRequest, database);
			database.executeTransaction(transactionRequest);
			if (id == 0) {
				id = transactionRequest.getResolvedRecordIdByCorrelationId(correlationId);
			}
		}
	}

	public void saveRecord(TransactionRequest transactionRequest, UniversalDB database) {
		if (entityChangeSet != null) {
			this.transactionRequest = transactionRequest;
			boolean update = !createEntity;
			TransactionRequestRecord record = TransactionRequestRecord.createOrUpdateRecord(transactionRequest, tableIndex, id, correlationId, update, entityChangeSet);
			entityChangeSet.setTransactionRequestRecordValues(transactionRequest, record, database);
			transactionRequest.addRecord(record);
			clearChanges();
			createEntity = false;
		}
	}

	public TableIndex getTableIndex() {
		return tableIndex;
	}

	@Override
	public int getTableId() {
		return tableIndex.getMappingId();
	}

	public String getQualifiedName() {
		return tableIndex.getFQN();
	}

	public void deleteRecord(UniversalDB database, int userId, long timestamp) {
		TransactionRequest transactionRequest = database.createTransactionRequest(userId, timestamp);
		TransactionRequestRecord deleteRecord = TransactionRequestRecord.createDeleteRecord(transactionRequest, tableIndex, id, entityChangeSet);
		transactionRequest.addRecord(deleteRecord);
		if (entityChangeSet != null) {
			entityChangeSet.setTransactionRecordMetaValues(deleteRecord, database);
		}
		clearChanges();
		database.executeTransaction(transactionRequest);
	}

	public void deleteRecord(UniversalDB database) {
		TransactionRequest transactionRequest = database.createTransactionRequest();
		TransactionRequestRecord deleteRecord = TransactionRequestRecord.createDeleteRecord(transactionRequest, tableIndex, id, entityChangeSet);
		transactionRequest.addRecord(deleteRecord);
		if (entityChangeSet != null) {
			entityChangeSet.setTransactionRecordMetaValues(deleteRecord, database);
		}
		clearChanges();
		database.executeTransaction(transactionRequest);
	}

	public void restoreDeletedRecord(UniversalDB database, int userId, long timestamp) {
		TransactionRequest transactionRequest = database.createTransactionRequest(userId, timestamp);
		TransactionRequestRecord restoreRecord = TransactionRequestRecord.createRestoreRecord(transactionRequest, tableIndex, id, entityChangeSet);
		transactionRequest.addRecord(restoreRecord);
		if (entityChangeSet != null) {
			entityChangeSet.setTransactionRecordMetaValues(restoreRecord, database);
		}
		clearChanges();
		database.executeTransaction(transactionRequest);
	}

	public void restoreDeletedRecord(UniversalDB database) {
		TransactionRequest transactionRequest = database.createTransactionRequest();
		TransactionRequestRecord restoreRecord = TransactionRequestRecord.createRestoreRecord(transactionRequest, tableIndex, id, entityChangeSet);
		transactionRequest.addRecord(restoreRecord);
		if (entityChangeSet != null) {
			entityChangeSet.setTransactionRecordMetaValues(restoreRecord, database);
		}
		clearChanges();
		database.executeTransaction(transactionRequest);
	}

	public boolean isRestorable() {
		return tableIndex.getTableModel().isRecoverableRecords();
	}

	@Override
	public boolean isStored() {
		return getId() > 0 && tableIndex.isStored(id);
	}

	@Override
	public boolean isDeleted() {
		return getId() > 0 && tableIndex.isDeleted(id);
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		AbstractUdbEntity that = (AbstractUdbEntity) o;
		if (getId() > 0 && getId() == that.getId()) {
			return true;
		}
		return getCorrelationId() > 0 && getCorrelationId() == that.getCorrelationId();
	}

	@Override
	public int hashCode() {
		if (getId() > 0) {
			return getId();
		} else {
			return getCorrelationId();
		}
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(tableIndex.getName()).append(": ").append(getId()).append("\n");
		List sortedFields = new ArrayList<>();
		sortedFields.addAll(tableIndex.getFieldIndices().stream().filter(column -> !Table.isReservedMetaName(column.getName())).toList());
		sortedFields.addAll(tableIndex.getFieldIndices().stream().filter(column -> Table.isReservedMetaName(column.getName())).toList());
		for (FieldIndex column : sortedFields) {
			sb.append("\t").append(column.getName()).append(": ").append(column.getStringValue(getId()));
			if (isChanged(column)) {
				TransactionRequestRecordValue changeValue = getChangeValue(column);
				sb.append(" -> ").append(changeValue.getValue());
			}
			sb.append("\n");
		}
		return sb.toString();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy