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.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.jparams.store.comparison.ComparisonPolicy;
import com.jparams.store.index.AbstractIndex;
import com.jparams.store.index.Index;
import com.jparams.store.index.IndexCreationException;
import com.jparams.store.index.IndexException;
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 Map> indexMap;
protected AbstractStore(final ReferenceManager referenceManager)
{
this.referenceManager = referenceManager;
this.indexMap = new HashMap<>();
}
protected AbstractStore(final ReferenceManager referenceManager, final Set> indexes)
{
this.referenceManager = referenceManager;
this.indexMap = indexes.stream().collect(Collectors.toMap(AbstractIndex::getName, Function.identity()));
}
@Override
public Index multiIndex(final String indexName, final KeyProvider, V> keyProvider, final ComparisonPolicy comparisonPolicy) throws IndexException
{
if (indexMap.containsKey(indexName))
{
throw new IllegalArgumentException("An index already exists with this name");
}
final AbstractIndex newIndex = createIndex(indexName, keyProvider, comparisonPolicy);
indexMap.put(indexName, newIndex);
indexReferences(Collections.singleton(newIndex), referenceManager.getReferences());
return newIndex;
}
@Override
public Index getIndex(final String indexName)
{
return indexMap.get(indexName);
}
@Override
public Collection> getIndexes()
{
return Collections.unmodifiableCollection(indexMap.values());
}
@Override
public boolean removeIndex(final Index index)
{
if (index.equals(indexMap.get(index.getName())))
{
indexMap.remove(index.getName());
return true;
}
return false;
}
@Override
public boolean removeIndex(final String indexName)
{
return indexMap.remove(indexName) != null;
}
@Override
public void reindex()
{
indexReferences(indexMap.values(), referenceManager.getReferences());
}
@Override
public void reindex(final V item)
{
reindex(Collections.singleton(item));
}
@Override
public void reindex(final Collection items)
{
indexReferences(indexMap.values(), items.stream()
.map(referenceManager::findReference)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList()));
}
@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 extends V> 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;
}
indexReferences(indexMap.values(), 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)
{
indexMap.values().forEach(index -> index.removeIndex(reference));
return true;
}
return false;
}
@Override
public void clear()
{
referenceManager.clear();
indexMap.values().forEach(AbstractIndex::clear);
}
@Override
public Store copy()
{
return createCopy(referenceManager, indexMap.values());
}
protected abstract Store createCopy(final ReferenceManager referenceManager, final Collection> indexes);
protected abstract AbstractIndex createIndex(String indexName, KeyProvider, V> keyProvider, ComparisonPolicy comparisonPolicy);
protected ReferenceManager getReferenceManager()
{
return referenceManager;
}
private static void indexReferences(final Collection> indexes, final Collection> references)
{
final List exceptions = new ArrayList<>();
for (final Reference reference : references)
{
for (final AbstractIndex, T> index : indexes)
{
try
{
index.index(reference);
}
catch (final IndexCreationException e)
{
exceptions.add(e);
}
}
}
if (!exceptions.isEmpty())
{
final String message = (exceptions.size() == 1 ? "1 exception" : exceptions.size() + " exceptions") + " occurred during indexing";
throw new IndexException(message, exceptions);
}
}
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();
indexMap.values().forEach(index -> index.removeIndex(previous));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy