com.eventsourcing.index.MemoryIndexEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eventsourcing-core Show documentation
Show all versions of eventsourcing-core Show documentation
Event capture and querying framework for Java
/**
* Copyright (c) 2016, All Contributors (see CONTRIBUTORS file)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.eventsourcing.index;
import com.eventsourcing.Entity;
import com.eventsourcing.EntityHandle;
import com.eventsourcing.Journal;
import com.eventsourcing.Repository;
import com.googlecode.cqengine.ConcurrentIndexedCollection;
import com.googlecode.cqengine.IndexedCollection;
import com.googlecode.cqengine.attribute.Attribute;
import com.googlecode.cqengine.attribute.MultiValueAttribute;
import com.googlecode.cqengine.index.compound.CompoundIndex;
import com.googlecode.cqengine.index.hash.HashIndex;
import com.googlecode.cqengine.index.navigable.NavigableIndex;
import com.googlecode.cqengine.index.radix.RadixTreeIndex;
import com.googlecode.cqengine.index.radixinverted.InvertedRadixTreeIndex;
import com.googlecode.cqengine.index.radixreversed.ReversedRadixTreeIndex;
import com.googlecode.cqengine.index.suffix.SuffixTreeIndex;
import com.googlecode.cqengine.index.unique.UniqueIndex;
import com.googlecode.cqengine.persistence.Persistence;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.query.option.QueryOptions;
import com.googlecode.cqengine.query.simple.Equal;
import com.googlecode.cqengine.resultset.ResultSet;
import org.osgi.service.component.annotations.Component;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
@Component(property = {"type=MemoryIndexEngine"})
public class MemoryIndexEngine extends CQIndexEngine implements IndexEngine {
@Override public String getType() {
return "MemoryIndexEngine";
}
@Override
public void setRepository(Repository repository) throws IllegalStateException {
if (isRunning()) {
throw new IllegalStateException();
}
this.repository = repository;
}
@Override
public void setJournal(Journal journal) throws IllegalStateException {
if (isRunning()) {
throw new IllegalStateException();
}
this.journal = journal;
}
@Override
protected List getIndexMatrix() {
return Arrays.asList(
new IndexCapabilities("Hash",
new IndexFeature[]{IndexFeature.EQ, IndexFeature.IN, IndexFeature.QZ},
attr -> HashIndex.onAttribute(compatibleAttribute(attr))),
new IndexCapabilities("Unique",
new IndexFeature[]{IndexFeature.UNIQUE, IndexFeature.EQ, IndexFeature.IN},
attr -> UniqueIndex.onAttribute(compatibleAttribute(attr))),
new IndexCapabilities("Compound",
new IndexFeature[]{IndexFeature.COMPOUND, IndexFeature.EQ, IndexFeature.IN, IndexFeature.QZ},
attrs -> {
Attribute[] attributes = (Attribute[]) Arrays.stream(attrs)
.map(attr -> compatibleAttribute(attr))
.toArray();
return CompoundIndex.onAttributes(attributes);
}),
new IndexCapabilities("Navigable",
new IndexFeature[]{IndexFeature.EQ, IndexFeature.IN, IndexFeature.QZ, IndexFeature.LT, IndexFeature.GT, IndexFeature.BT},
attr -> NavigableIndex.onAttribute(compatibleAttribute(attr))),
new IndexCapabilities("RadixTree",
new IndexFeature[]{IndexFeature.EQ, IndexFeature.IN, IndexFeature.SW},
attr -> RadixTreeIndex.onAttribute(compatibleAttribute(attr))),
new IndexCapabilities("ReversedRadixTree",
new IndexFeature[]{IndexFeature.EQ, IndexFeature.IN, IndexFeature.EW},
attr -> ReversedRadixTreeIndex.onAttribute(compatibleAttribute(attr))),
new IndexCapabilities("InvertedRadixTree",
new IndexFeature[]{IndexFeature.EQ, IndexFeature.IN, IndexFeature.CI},
attr -> InvertedRadixTreeIndex.onAttribute(compatibleAttribute(attr))),
new IndexCapabilities("SuffixTree",
new IndexFeature[]{IndexFeature.EQ, IndexFeature.IN, IndexFeature.EW, IndexFeature.SC},
attr -> SuffixTreeIndex.onAttribute(compatibleAttribute(attr)))
);
}
@Override protected IndexedCollection>
createIndexedCollection(Persistence, ? extends Comparable> persistence) {
return new ConcurrentMemoryIndexedCollection<>(persistence);
}
private static class ConcurrentMemoryIndexedCollection extends ConcurrentIndexedCollection {
public ConcurrentMemoryIndexedCollection() {
super();
}
public ConcurrentMemoryIndexedCollection(
Persistence persistence) {
super(persistence);
}
@Override public ResultSet retrieve(Query query) {
return super.retrieve(compatibleQuery(query));
}
@Override public ResultSet retrieve(Query query, QueryOptions queryOptions) {
return super.retrieve(compatibleQuery(query), queryOptions);
}
private Query compatibleQuery(Query query) {
if (query instanceof Equal) {
if (((Equal) query).getAttributeType() == byte[].class) {
Equal newQuery = new SpecialEquality<>(query);
return newQuery;
}
}
return query;
}
private static class SpecialEquality extends Equal {
public SpecialEquality(Query query) {
super(compatibleAttribute(((Equal) query).getAttribute()), ((Equal) query).getValue());
}
@Override
protected boolean matchesNonSimpleAttribute(Attribute attribute, O object,
QueryOptions queryOptions) {
for (Object attributeValue : attribute.getValues(object, queryOptions)) {
if (attributeValue.equals(getValue())) {
return true;
}
}
return false;
}
@Override public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Equal)) return false;
Equal equal = (Equal) o;
if (!equal.getAttribute().equals(getAttribute())) return false;
if (!equal.getValue().equals(getValue())) return false;
return true;
}
}
}
public static Attribute, ?> compatibleAttribute(Attribute, A>
attribute) {
if (attribute.getAttributeType() == byte[].class) {
return new ByteArrayWrappingAttribute<>((Attribute, byte[]>) attribute);
} else {
return attribute;
}
}
private static class ByteArrayWrappingAttribute
extends MultiValueAttribute, ByteArray> {
private final Attribute, byte[]> attribute;
public ByteArrayWrappingAttribute(Attribute, byte[]> attribute) {
this.attribute = attribute;
}
@Override public String getAttributeName() {
return attribute.getAttributeName();
}
@Override public Iterable getValues(EntityHandle object, QueryOptions queryOptions) {
ArrayList objects = new ArrayList<>();
Iterable values = attribute.getValues(object, queryOptions);
Iterator iterator = values.iterator();
while (iterator.hasNext()) {
objects.add(new ByteArray(iterator.next()));
}
return objects;
}
@Override public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o.equals(attribute)) {
return true;
}
return super.equals(o);
}
}
private static class ByteArray implements Comparable {
private final byte[] bytes;
private ByteArray(byte[] bytes) {this.bytes = bytes;}
@Override public boolean equals(Object obj) {
if (!(obj instanceof byte[]) && !(obj instanceof ByteArray)) {
return false;
}
if (obj instanceof ByteArray) {
return ByteBuffer.wrap(bytes).equals(ByteBuffer.wrap(((ByteArray) obj).bytes));
}
return ByteBuffer.wrap(bytes).equals(ByteBuffer.wrap((byte[]) obj));
}
@Override public int compareTo(Object o) {
if (!(o instanceof byte[])) {
return -1;
}
return ByteBuffer.wrap(bytes).compareTo(ByteBuffer.wrap((byte[]) o));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy