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

is.codion.framework.model.DefaultForeignKeyDetailModelLink Maven / Gradle / Ivy

/*
 * This file is part of Codion.
 *
 * Codion is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Codion is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Codion.  If not, see .
 *
 * Copyright (c) 2022 - 2024, Björn Darri Sigurðsson.
 */
package is.codion.framework.model;

import is.codion.common.state.State;
import is.codion.framework.domain.entity.Entity;
import is.codion.framework.domain.entity.attribute.ForeignKey;

import java.util.Collection;
import java.util.Map;

import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;

/**
 * A default {@link ForeignKeyDetailModelLink} implementation.
 * @param  the {@link EntityModel} type
 * @param  the {@link EntityEditModel} type
 * @param  the {@link EntityTableModel} type
 */
public class DefaultForeignKeyDetailModelLink, E extends AbstractEntityEditModel,
				T extends EntityTableModel> extends DefaultDetailModelLink implements ForeignKeyDetailModelLink {

	private final ForeignKey foreignKey;
	private final State clearForeignKeyOnEmptySelection = State.state(ForeignKeyDetailModelLink.CLEAR_FOREIGN_KEY_ON_EMPTY_SELECTION.get());
	private final State searchByInsertedEntity = State.state(ForeignKeyDetailModelLink.SEARCH_BY_INSERTED_ENTITY.get());
	private final State refreshOnSelection = State.state(ForeignKeyDetailModelLink.REFRESH_ON_SELECTION.get());

	/**
	 * @param detailModel the detail model
	 * @param foreignKey the foreign key to base this link on
	 */
	public DefaultForeignKeyDetailModelLink(M detailModel, ForeignKey foreignKey) {
		super(detailModel);
		this.foreignKey = requireNonNull(foreignKey, "foreignKey");
	}

	@Override
	public final ForeignKey foreignKey() {
		return foreignKey;
	}

	@Override
	public final State searchByInsertedEntity() {
		return searchByInsertedEntity;
	}

	@Override
	public final State refreshOnSelection() {
		return refreshOnSelection;
	}

	@Override
	public final State clearForeignKeyOnEmptySelection() {
		return clearForeignKeyOnEmptySelection;
	}

	@Override
	public void onSelection(Collection selectedEntities) {
		if (detailModel().containsTableModel() &&
						setForeignKeyCondition(selectedEntities) && refreshOnSelection.get()) {
			detailModel().tableModel().refresher().refreshThen(items -> setEditModelForeignKeyValue(selectedEntities));
		}
		else {
			setEditModelForeignKeyValue(selectedEntities);
		}
	}

	@Override
	public void onInsert(Collection insertedEntities) {
		Collection entities = ofReferencedType(insertedEntities);
		detailModel().editModel().add(foreignKey, entities);
		if (!entities.isEmpty()) {
			detailModel().editModel().put(foreignKey, entities.iterator().next());
		}
		if (detailModel().containsTableModel() &&
						searchByInsertedEntity.get() && setForeignKeyCondition(entities)) {
			detailModel().tableModel().refresh();
		}
	}

	@Override
	public void onUpdate(Map updatedEntities) {
		Collection entities = ofReferencedType(updatedEntities.values());
		detailModel().editModel().replace(foreignKey, entities);
		if (detailModel().containsTableModel() &&
						// These will be replaced by the table model if it handles edit events
						detailModel().tableModel().handleEditEvents().not().get()) {
			detailModel().tableModel().replace(foreignKey, entities);
		}
	}

	@Override
	public void onDelete(Collection deletedEntities) {
		detailModel().editModel().remove(foreignKey, ofReferencedType(deletedEntities));
	}

	private Collection ofReferencedType(Collection entities) {
		return entities.stream()
						.filter(entity -> entity.entityType().equals(foreignKey.referencedType()))
						.collect(toList());
	}

	private void setEditModelForeignKeyValue(Collection selectedEntities) {
		Entity foreignKeyValue = selectedEntities.isEmpty() ? null : selectedEntities.iterator().next();
		if (detailModel().editModel().exists().not().get() && (foreignKeyValue != null || clearForeignKeyOnEmptySelection.get())) {
			detailModel().editModel().put(foreignKey, foreignKeyValue);
		}
	}

	private boolean setForeignKeyCondition(Collection selectedEntities) {
		return detailModel().tableModel().conditionModel()
						.setInConditionValues(foreignKey, selectedEntities);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy