
is.codion.framework.domain.test.DefaultEntityFactory 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) 2021 - 2024, Björn Darri Sigurðsson.
*/
package is.codion.framework.domain.test;
import is.codion.common.db.exception.DatabaseException;
import is.codion.common.item.Item;
import is.codion.framework.db.EntityConnection;
import is.codion.framework.domain.entity.Entities;
import is.codion.framework.domain.entity.Entity;
import is.codion.framework.domain.entity.EntityDefinition;
import is.codion.framework.domain.entity.EntityType;
import is.codion.framework.domain.entity.attribute.Attribute;
import is.codion.framework.domain.entity.attribute.AttributeDefinition;
import is.codion.framework.domain.entity.attribute.Column;
import is.codion.framework.domain.entity.attribute.ColumnDefinition;
import is.codion.framework.domain.entity.attribute.ForeignKey;
import is.codion.framework.domain.entity.attribute.ForeignKeyDefinition;
import is.codion.framework.domain.test.DomainTest.EntityFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.stream.IntStream;
import static java.util.Collections.singletonList;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
/**
* Handles creating and manipulating Entity instances for testing purposes.
*/
public class DefaultEntityFactory implements EntityFactory {
private static final Logger LOG = LoggerFactory.getLogger(DefaultEntityFactory.class);
private static final int MININUM_RANDOM_NUMBER = -10_000;
private static final int MAXIMUM_RANDOM_NUMBER = 10_000;
private static final int MAXIMUM_RANDOM_STRING_LENGTH = 10;
private static final String ALPHA_NUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final Random RANDOM = new Random();
private final EntityConnection connection;
private final Entities entities;
private final Map foreignKeyEntities = new HashMap<>();
/**
* Instantiates a new {@link DefaultEntityFactory}
* @param connection the connection to use
*/
public DefaultEntityFactory(EntityConnection connection) {
this.connection = requireNonNull(connection);
this.entities = connection.entities();
}
@Override
public Entity entity(EntityType entityType) throws DatabaseException {
Entity entity = entities.entity(requireNonNull(entityType));
populate(entity, insertableColumns(entities.definition(entityType)));
return entity;
}
@Override
public Optional entity(ForeignKey foreignKey) throws DatabaseException {
if (entities.definition(requireNonNull(foreignKey).referencedType()).readOnly()) {
return Optional.empty();
}
if (foreignKeyEntities.containsKey(foreignKey)) {
return Optional.ofNullable(foreignKeyEntities.get(foreignKey));
}
foreignKeyEntities.put(foreignKey, null);// short curcuit recursion
Entity entity = insertOrSelect(entity(foreignKey.referencedType()), connection);
foreignKeyEntities.put(foreignKey, entity);
return Optional.of(entity);
}
@Override
public void modify(Entity entity) throws DatabaseException {
populate(requireNonNull(entity), updatableColumns(entity.definition()));
}
/**
* @return the underlying {@link EntityConnection} instance
*/
protected final EntityConnection connection() {
return connection;
}
/**
* @return the underlying {@link Entities} instance
*/
protected final Entities entities() {
return entities;
}
/**
* Creates a value for the given attribute.
* @param attribute the attribute
* @param the attribute value type
* @return a random value
* @throws DatabaseException in case of an exception
*/
protected T value(Attribute attribute) throws DatabaseException {
requireNonNull(attribute, "attribute");
AttributeDefinition attributeDefinition = entities.definition(attribute.entityType()).attributes().definition(attribute);
try {
if (attributeDefinition instanceof ForeignKeyDefinition) {
return (T) entity(((ForeignKeyDefinition) attributeDefinition).attribute()).orElse(null);
}
if (!attributeDefinition.items().isEmpty()) {
return randomItem(attributeDefinition);
}
if (attribute.type().isBoolean()) {
return (T) Boolean.valueOf(RANDOM.nextBoolean());
}
if (attribute.type().isCharacter()) {
return (T) Character.valueOf((char) RANDOM.nextInt());
}
if (attribute.type().isLocalDate()) {
return (T) LocalDate.now();
}
if (attribute.type().isLocalDateTime()) {
return (T) LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS);
}
if (attribute.type().isOffsetDateTime()) {
return (T) OffsetDateTime.now().truncatedTo(ChronoUnit.SECONDS);
}
if (attribute.type().isLocalTime()) {
return (T) LocalTime.now().truncatedTo(ChronoUnit.SECONDS);
}
if (attribute.type().isDouble()) {
return (T) Double.valueOf(randomDouble(attributeDefinition));
}
if (attribute.type().isBigDecimal()) {
return (T) BigDecimal.valueOf(randomDouble(attributeDefinition));
}
if (attribute.type().isInteger()) {
return (T) Integer.valueOf(randomInteger(attributeDefinition));
}
if (attribute.type().isLong()) {
return (T) Long.valueOf(randomLong(attributeDefinition));
}
if (attribute.type().isShort()) {
return (T) Short.valueOf(randomShort(attributeDefinition));
}
if (attribute.type().isString()) {
return (T) randomString(attributeDefinition);
}
if (attribute.type().isByteArray()) {
return (T) randomByteArray(attributeDefinition);
}
if (attribute.type().isEnum()) {
return randomEnum(attribute);
}
return null;
}
catch (Exception e) {
LOG.error("Exception while fetching a value for: {}", attributeDefinition.attribute(), e);
if (e instanceof RuntimeException) {
throw e;
}
if (e instanceof DatabaseException) {
throw e;
}
throw new RuntimeException(e);
}
}
private void populate(Entity entity, Collection> columns) throws DatabaseException {
EntityDefinition definition = entity.definition();
for (Column> column : columns) {
if (!definition.foreignKeys().foreignKeyColumn(column)) {
entity.put((Attribute
© 2015 - 2025 Weber Informatics LLC | Privacy Policy