com.jparams.store.AbstractStore Maven / Gradle / Ivy
package com.jparams.store;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import com.jparams.store.index.Index;
import com.jparams.store.index.IndexDefinition;
import com.jparams.store.index.IndexException;
import com.jparams.store.index.IndexManager;
import com.jparams.store.query.IndexMatch;
import com.jparams.store.query.Operator;
import com.jparams.store.query.Query;
import com.jparams.store.query.QueryDefinition;
import com.jparams.store.reference.Reference;
import com.jparams.store.reference.ReferenceManager;
public abstract class AbstractStore extends AbstractCollection implements Store
{
private final ReferenceManager referenceManager;
private final IndexManager indexManager;
protected AbstractStore(final ReferenceManager referenceManager, final IndexManager indexManager)
{
this.referenceManager = referenceManager;
this.indexManager = indexManager;
}
@Override
public List get(final Query query, final Integer limit)
{
final QueryDefinition definition = query.build();
final List indexMatches = definition.getIndexMatches();
final Operator operator = definition.getOperator();
final Set> results = new LinkedHashSet<>();
boolean firstMatch = true;
for (final IndexMatch indexMatch : indexMatches)
{
final Set> references = Optional.ofNullable(indexManager.getIndex(indexMatch.getIndexName()))
.map(index -> index.getReferences(indexMatch.getKey()))
.orElse(Collections.emptySet());
if (firstMatch || operator == Operator.OR)
{
results.addAll(references);
firstMatch = false;
}
else
{
results.retainAll(references);
}
}
return results.stream()
.map(Reference::get)
.limit(limit == null ? Long.MAX_VALUE : limit)
.collect(Collectors.toList());
}
@Override
public Index index(final String indexName, final IndexDefinition indexDefinition) throws IndexException
{
return indexManager.createIndex(indexName, indexDefinition, referenceManager.getReferences());
}
@Override
public Index getIndex(final String indexName)
{
return indexManager.getIndex(indexName);
}
@Override
public Collection> getIndexes()
{
return indexManager.getIndexes();
}
@Override
public boolean removeIndex(final Index index)
{
return indexManager.removeIndex(index);
}
@Override
public boolean removeIndex(final String indexName)
{
return indexManager.removeIndex(indexName);
}
@Override
public void reindex()
{
indexManager.reindex(referenceManager.getReferences());
}
@Override
public void reindex(final V item)
{
reindex(Collections.singleton(item));
}
@Override
public void reindex(final Collection items)
{
final List> references = items.stream()
.map(referenceManager::findReference)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
indexManager.reindex(references);
}
@Override
public int size()
{
return referenceManager.size();
}
@Override
public boolean isEmpty()
{
return size() == 0;
}
@Override
public boolean contains(final Object obj)
{
return referenceManager.findReference(obj).isPresent();
}
@Override
public Iterator iterator()
{
return new StoreIterator(referenceManager.getReferences().iterator());
}
@Override
public boolean addAll(final Collection collection)
{
final List> references = new ArrayList<>();
boolean changed = false;
for (final V item : collection)
{
final Optional> existingReference = referenceManager.findReference(item);
if (existingReference.isPresent())
{
references.add(existingReference.get());
continue;
}
references.add(referenceManager.add(item));
changed = true;
}
indexManager.reindex(references);
return changed;
}
@Override
public boolean add(final V item)
{
return addAll(Collections.singleton(item));
}
@Override
public boolean remove(final Object obj)
{
final Reference reference = referenceManager.remove(obj);
if (reference != null)
{
indexManager.removeReference(reference);
return true;
}
return false;
}
@Override
public void clear()
{
referenceManager.clear();
indexManager.clear();
}
@Override
public Store copy()
{
return createCopy(referenceManager, indexManager);
}
protected abstract Store createCopy(final ReferenceManager referenceManager, final IndexManager indexManager);
protected ReferenceManager getReferenceManager()
{
return referenceManager;
}
private class StoreIterator implements Iterator
{
private final Iterator> iterator;
private Reference previous;
StoreIterator(final Iterator> iterator)
{
this.iterator = iterator;
}
@Override
public boolean hasNext()
{
return iterator.hasNext();
}
@Override
public V next()
{
previous = iterator.next();
return previous.get();
}
@Override
public void remove()
{
iterator.remove();
indexManager.removeReference(previous);
}
}
}