package org.molgenis.data.mem;
import com.google.common.collect.Sets;
import org.molgenis.data.*;
import org.molgenis.data.QueryRule.Operator;
import org.molgenis.data.aggregation.AggregateQuery;
import org.molgenis.data.aggregation.AggregateResult;
import org.molgenis.data.meta.model.EntityType;
import org.molgenis.data.support.QueryImpl;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Stream;
import static com.google.common.collect.Iterables.partition;
/**
* Repository that uses a hash map as store.
* <p>
* For testing purposes
*/
public class InMemoryRepository implements Repository<Entity>
{
private final EntityType metadata;
private final Map<Object, Entity> entities = new LinkedHashMap<>();
public InMemoryRepository(EntityType entityType)
{
this.metadata = entityType;
}
@Override
public String getName()
{
return metadata.getName();
}
public EntityType getEntityType()
{
return metadata;
}
@Override
public Iterator<Entity> iterator()
{
return entities.values().iterator();
}
@Override
public void forEachBatched(Fetch fetch, Consumer<List<Entity>> consumer, int batchSize)
{
for (List<Entity> batch : partition(entities.values(), batchSize))
{
consumer.accept(batch);
}
}
@Override
public void close() throws IOException
{
}
@Override
public Query<Entity> query()
{
throw new UnsupportedOperationException();
}
@Override
public long count(Query<Entity> q)
{
return entities.size();
}
@Override
public Stream<Entity> findAll(Query<Entity> q)
{
if (new QueryImpl<>().equals(q))
{
return entities.values().stream();
}
else
{
// partial implementation: one EQUALS rule
if (q.getRules().size() == 1)
{
QueryRule r = q.getRules().iterator().next();
if (r.getOperator() == Operator.EQUALS)
{
return entities.entrySet().stream().map((e) ->
{
if (e.getValue().get(r.getField()).equals(r.getValue()))
{
return e.getValue();
}
else
{
return null;
}
}).filter(Objects::nonNull);
}
}
throw new UnsupportedOperationException();
}
}
@Override
public Entity findOne(Query<Entity> q)
{
throw new UnsupportedOperationException();
}
@Override
public Entity findOneById(Object id)
{
return findOneById(id, null);
}
@Override
public Entity findOneById(Object id, Fetch fetch)
{
return entities.get(id);
}
@Override
public Stream<Entity> findAll(Stream<Object> ids)
{
return ids.map(entities::get).filter(Objects::nonNull);
}
@Override
public Stream<Entity> findAll(Stream<Object> ids, Fetch fetch)
{
return ids.map(entities::get).filter(Objects::nonNull);
}
@Override
public long count()
{
return entities.size();
}
@Override
public void update(Entity entity)
{
Object id = getId(entity);
if (!entities.containsKey(id))
{
throw new IllegalStateException("No entity with id " + id);
}
entities.put(id, entity);
}
@Override
public void update(Stream<Entity> entities)
{
entities.forEach(this::update);
}
private Object getId(Entity entity)
{
return entity.get(metadata.getIdAttribute().getName());
}
@Override
public void delete(Entity entity)
{
deleteById(getId(entity));
}
@Override
public void delete(Stream<Entity> entities)
{
entities.forEach(this::delete);
}
@Override
public void deleteById(Object id)
{
entities.remove(id);
}
@Override
public void deleteAll(Stream<Object> ids)
{
ids.forEach(this::deleteById);
}
@Override
public void deleteAll()
{
entities.clear();
}
@Override
public void add(Entity entity)
{
Object id = getId(entity);
if (id == null)
{
throw new NullPointerException("Entity ID is null.");
}
if (entities.containsKey(id))
{
throw new IllegalStateException("Entity with id " + id + " already exists");
}
entities.put(id, entity);
}
@Override
public Integer add(Stream<Entity> entities)
{
AtomicInteger count = new AtomicInteger();
entities.forEach(entity ->
{
add(entity);
count.incrementAndGet();
});
return count.get();
}
@Override
public Set<RepositoryCapability> getCapabilities()
{
return Sets.newHashSet(RepositoryCapability.QUERYABLE, RepositoryCapability.WRITABLE);
}
@Override
public Set<Operator> getQueryOperators()
{
return EnumSet.allOf(Operator.class);
}
@Override
public AggregateResult aggregate(AggregateQuery aggregateQuery)
{
throw new UnsupportedOperationException();
}
}