package io.vivarium.persistence;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.google.common.base.Preconditions;
import io.vivarium.core.GridWorldBlueprint;
import io.vivarium.core.Creature;
import io.vivarium.core.CreatureBlueprint;
import io.vivarium.core.GridWorld;
import io.vivarium.core.processor.Processor;
import io.vivarium.db.DatabaseUtils;
import io.vivarium.db.Relation;
import io.vivarium.serialization.JSONConverter;
import io.vivarium.serialization.VivariumObjectCollection;
import io.vivarium.util.UUID;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@EqualsAndHashCode(callSuper = true)
@ToString
public class ResourceModel extends PersistenceModel
{
// Table name
private static final String TABLE_NAME = "resources";
// Column names
private static final String ID = "id";
private static final String DATA = "data";
private static final String FILE_FORMAT_VERSION = "file_format_version";
private static final String WORLD_COUNT = "world_count";
private static final String BLUEPRINT_COUNT = "blueprint_count";
private static final String SPECIES_COUNT = "species_count";
private static final String CREATURE_COUNT = "creature_count";
private static final String PROCESSOR_COUNT = "processor_count";
// relation data
public final UUID resourceID;
public final Optional<String> jsonData;
public final Optional<Integer> fileFormatVersion;
public ResourceModel(UUID resourceID, String jsonData, Integer fileFormatVersion)
{
Preconditions.checkNotNull(resourceID, "resourceID cannot be null");
this.resourceID = resourceID;
this.jsonData = jsonData != null ? Optional.of(jsonData) : Optional.empty();
this.fileFormatVersion = fileFormatVersion != null ? Optional.of(fileFormatVersion) : Optional.empty();
}
static Optional<ResourceModel> getFromDatabase(Connection connection, UUID resourceID) throws SQLException
{
List<Map<String, Object>> relations = DatabaseUtils.select(connection, TABLE_NAME,
Optional.of(Relation.equalTo(ID, resourceID)));
if (relations.size() == 1)
{
Map<String, Object> relation = relations.get(0);
ResourceModel resource = new ResourceModel(UUID.fromString(relation.get(ID).toString()),
relation.get(DATA).toString(), (Integer) relation.get(FILE_FORMAT_VERSION));
return Optional.of(resource);
}
else if (relations.isEmpty())
{
return Optional.empty();
}
else
{
throw new IllegalStateException("Select of Resource returned multiple objects");
}
}
@Override
public void persistToDatabase(Connection connection) throws SQLException
{
Map<String, Object> resourceRelation = new HashMap<>();
resourceRelation.put(ID, resourceID);
resourceRelation.put(DATA, jsonData.isPresent() ? jsonData.get() : null);
resourceRelation.put(FILE_FORMAT_VERSION, fileFormatVersion.isPresent() ? fileFormatVersion.get() : null);
resourceRelation.put(WORLD_COUNT, null);
resourceRelation.put(BLUEPRINT_COUNT, null);
resourceRelation.put(SPECIES_COUNT, null);
resourceRelation.put(CREATURE_COUNT, null);
resourceRelation.put(PROCESSOR_COUNT, null);
if (jsonData.isPresent())
{
VivariumObjectCollection collection = JSONConverter.jsonStringToSerializerCollection(jsonData.get());
resourceRelation.put(WORLD_COUNT, collection.getAll(GridWorld.class).size());
resourceRelation.put(BLUEPRINT_COUNT, collection.getAll(GridWorldBlueprint.class).size());
resourceRelation.put(SPECIES_COUNT, collection.getAll(CreatureBlueprint.class).size());
resourceRelation.put(CREATURE_COUNT, collection.getAll(Creature.class).size());
resourceRelation.put(PROCESSOR_COUNT, collection.getAll(Processor.class).size());
}
DatabaseUtils.upsert(connection, TABLE_NAME, resourceRelation, getPrimaryKeys());
connection.commit();
}
private List<String> getPrimaryKeys()
{
List<String> primaryKeys = new LinkedList<>();
primaryKeys.add(ID);
return primaryKeys;
}
}