/**
 * Copyright 2016 Eventchain team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 */
package org.eventchain;

import com.google.common.util.concurrent.Service;
import org.eventchain.hlc.PhysicalTimeProvider;
import org.eventchain.index.IndexEngine;

import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
 * Repository is holder of resources necessary to
 * facilitate Eventchain operations.
 */
public interface Repository extends Service {

    /**
     * Creates a default Repository
     * @return
     */
    static Repository create() {
        return new RepositoryImpl();
    }

    /**
     * Sets journal to be used in this repository
     *
     * Should be done before invoking {@link #startAsync()}
     *
     * @param journal
     * @throws IllegalStateException if called after the service is started
     */
    void setJournal(Journal journal) throws IllegalStateException;

    /**
     * Sets index engine to be used in this repository
     *
     * Should be done before invoking {@link #startAsync()}
     *
     * @param indexEngine
     * @throws IllegalStateException if called after the service is started
     */
    void setIndexEngine(IndexEngine indexEngine) throws IllegalStateException;

    /**
     * Get index engine as previously configured. Useful for querying.
     *
     * @return null if index engine was not configured yet.
     */
    IndexEngine getIndexEngine();

    /**
     * Sets physical time provider
     *
     * @param timeProvider
     */
    void setPhysicalTimeProvider(PhysicalTimeProvider timeProvider) throws IllegalStateException;

    /**
     * Sets lock provider
     *
     * @param lockProvider
     */
    void setLockProvider(LockProvider lockProvider) throws IllegalStateException;

    /**
     * Sets package hierarchy for command and event discovery.
     *
     * Should be done before invoking {@link #startAsync()}
     *
     * @param pkg
     * @throws IllegalStateException if called after the service is started
     */
    void setPackage(Package pkg) throws IllegalStateException;


    /**
     * Returns a set of commands discovered or configured
     * with this repository
     *
     * @return
     */
    Set<Class<? extends Command>> getCommands();

    /**
     * Returns a set of events discovered or configured
     * with this repository
     *
     * @return
     */
    Set<Class<? extends Event>> getEvents();

    /**
     * Publishes command asynchronously
     *
     * @param command
     * @param <T> Command class
     * @param <C> Result class
     * @return {@link CompletableFuture} with command's result
     */
    <T extends Command<C>, C>  CompletableFuture<C> publish(T command);

}

@@ -634,16 +634,221 @@
 ervice;%0A
+import com.googlecode.cqengine.query.Query;%0Aimport com.googlecode.cqengine.query.QueryFactory;%0Aimport com.googlecode.cqengine.query.option.QueryOptions;%0Aimport com.googlecode.cqengine.resultset.ResultSet;%0A
 import o
@@ -999,16 +999,90 @@
 uture;%0A%0A
+import static com.googlecode.cqengine.query.QueryFactory.noQueryOptions;%0A%0A
 /**%0A * R
@@ -3462,10 +3462,1030 @@
 mand);%0A%0A
+    /**%0A     * Shortcut method for accessing index retrieval (see %7B@link #query(Class, Query, QueryOptions)%7D with%0A     * %7B@link QueryFactory#noQueryOptions()%7D specified as %7B@link QueryOptions%7D%0A     *%0A     * @param klass%0A     * @param query%0A     * @param %3CE%3E%0A     * @return%0A     */%0A    default %3CE extends Entity%3E ResultSet%3CEntityHandle%3CE%3E%3E query(Class%3CE%3E klass, Query%3CEntityHandle%3CE%3E%3E query) %7B%0A        return query(klass, query, noQueryOptions());%0A    %7D%0A%0A    /**%0A     * Shortcut method for accessing index querying.%0A     *%0A     * %3Cp%3EExample:%3C/p%3E%0A     *%0A     * %7B@code%0A     * repository.query(UserCreated.class, equal(UserCreated.EMAIL, email), noQueryOptions())%0A     * %7D%0A     *%0A     * @param klass%0A     * @param query%0A     * @param queryOptions%0A     * @param %3CE%3E%0A     * @return%0A     */%0A    default %3CE extends Entity%3E ResultSet%3CEntityHandle%3CE%3E%3E query(Class%3CE%3E klass, Query%3CEntityHandle%3CE%3E%3E query, QueryOptions queryOptions) %7B%0A        return getIndexEngine().getIndexedCollection(klass).retrieve(query, queryOptions);%0A    %7D%0A
 %7D%0A

Add convenience querying methods to Repository