All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.eventsourcing.index.MemoryIndexEngine Maven / Gradle / Ivy

There is a newer version: 0.4.6
Show newest version
/**
 * 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