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

com.eventsourcing.index.CascadingIndexEngine 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.Journal;
import com.eventsourcing.Repository;
import com.google.common.base.Joiner;
import com.googlecode.cqengine.index.Index;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.*;

import javax.management.openmbean.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Cascading index engine allows to combine multiple engines behind a singular {@link IndexEngine} interface.
 * 

* The order of index engines is important is evaluated "left to right", i.e. those added earlier will be given a higher * priority. The way cascading works is if an index engine in the list does not support a specific type of index, * next one in the list will be tried, until the list is exhausted. *

* In an OSGi environment, indexEngine property must be configured to ensure intended ordering. This property * should have a comma-delimited list of fully qualified class names for index engines to be used. It can list index engines * that are not available through references. They will be ignored. */ @Slf4j @Component(property = {"indexEngines=", "type=CascadingIndexEngine", "jmx.objectname=com.eventsourcing.index.IndexEngine:type=CascadingIndexEngine" }, configurationPolicy = ConfigurationPolicy.REQUIRE) public class CascadingIndexEngine extends CQIndexEngine implements IndexEngine, CascadingIndexEngineMBean { @Override public String getType() { return "CascadingIndexEngine"; } private List indexEngines = new ArrayList<>(); @Getter private String[] configuredIndexEngines; public CascadingIndexEngine() { } public CascadingIndexEngine(IndexEngine... indexEngines) { this.indexEngines = Arrays.asList(indexEngines); } @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, target = "(!(service.pid=com.eventsourcing.index.CascadingIndexEngine))") public void addIndexEngine(IndexEngine indexEngine) { indexEngine.setJournal(journal); indexEngine.setRepository(repository); indexEngines.add(indexEngine); sortIndexEngines(); } protected void sortIndexEngines() { if (configuredIndexEngines != null) { indexEngines = Arrays.asList(configuredIndexEngines).stream(). map(name -> indexEngines.stream().filter(e -> e.getType().contentEquals(name)) .findFirst()). filter(Optional::isPresent). map(Optional::get). collect(Collectors.toList()); } } public void removeIndexEngine(IndexEngine indexEngine) { indexEngines.remove(indexEngine); } @Activate protected void activate(ComponentContext ctx) { configuredIndexEngines = ((String) ctx.getProperties().get("indexEngines")).split(","); sortIndexEngines(); } public String[] getIndexEngines() { return indexEngines.stream().map(IndexEngine::getType).toArray(String[]::new); } @Override public void setJournal(Journal journal) throws IllegalStateException { this.journal = journal; } @Override public void setRepository(Repository repository) throws IllegalStateException { this.repository = repository; } private Map decisions = new HashMap<>(); @Override public Index getIndexOnAttribute(Attribute attribute, IndexFeature... features) throws IndexNotSupported { for (IndexEngine engine : indexEngines) { try { Index index = engine.getIndexOnAttribute(attribute, features); decisions.put(Joiner.on(", ").join(features) + " on " + attribute.toString(), engine); return index; } catch (IndexNotSupported e) { } } throw new IndexNotSupported(new Attribute[]{attribute}, features, this); } @Override public Index getIndexOnAttributes(Attribute[] attributes, IndexFeature... features) throws IndexNotSupported { for (IndexEngine engine : indexEngines) { try { Index index = engine.getIndexOnAttributes(attributes, features); for (Attribute attribute : attributes) { decisions.put(Joiner.on(", ").join(features) + " on " + attribute.toString(), engine); } return index; } catch (IndexNotSupported e) { } } throw new IndexNotSupported(attributes, features, this); } @Override public String toString() { return "CascadingIndexEngine[" + Joiner.on(", ").join(indexEngines) + "]"; } @Override protected void doStart() { super.doStart(); } // MBean @Override protected List getIndexMatrix() { return Collections.emptyList(); } @SneakyThrows @Override public TabularData getCascadingDecisions() { CompositeType type = new CompositeType("Decision", "Cascading decision", new String[]{"Index", "Engine"}, new String[]{"Index", "Index Engine"}, new OpenType[]{SimpleType.STRING, SimpleType.STRING}); TabularDataSupport tab = new TabularDataSupport( new TabularType("Decisions", "Cascading decisions", type, new String[]{"Index"})); for (Map.Entry entry : decisions.entrySet()) { tab.put(new CompositeDataSupport(type, new String[]{"Index", "Engine"}, new Object[]{entry.getKey(), entry.getValue().getType()})); } return tab; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy