// Path: joiner-core/src/test/java/cz/encircled/joiner/core/TestException.java
// public class TestException extends RuntimeException {
// }
// 
// Path: joiner-core/src/main/java/cz/encircled/joiner/query/ExtendedJPAQuery.java
// public class ExtendedJPAQuery<T> extends JPAQuery<T> {
// 
//     public ExtendedJPAQuery(EntityManager entityManager, JPAQuery<T> another) {
//         super(entityManager, another.getMetadata().clone());
//         clone(another);
//     }
// 
//     public JPQLSerializer getSerializer(boolean forCount) {
//         return serialize(forCount);
//     }
// 
// }
// 
// Path: joiner-core/src/main/java/cz/encircled/joiner/query/JoinerQuery.java
// public interface JoinerQuery<T, R> extends JoinRoot {
// 
//     EntityPath<T> getFrom();
// 
//     Expression<R> getReturnProjection();
// 
//     JoinerQuery<T, R> where(Predicate where);
// 
//     Predicate getWhere();
// 
//     JoinerQuery<T, R> distinct(boolean isDistinct);
// 
//     boolean isDistinct();
// 
//     JoinerQuery<T, R> groupBy(Path<?> groupBy);
// 
//     Path<?> getGroupBy();
// 
//     JoinerQuery<T, R> having(Predicate having);
// 
//     Predicate getHaving();
// 
//     /**
//      * Add join graphs to the query.
//      *
//      * @param names names of join graphs
//      * @return this
//      * @see cz.encircled.joiner.query.join.JoinGraphRegistry
//      */
//     JoinerQuery<T, R> joinGraphs(String... names);
// 
//     /**
//      * Add join graphs to the query.
//      *
//      * @param names names of join graphs
//      * @return this
//      * @see cz.encircled.joiner.query.join.JoinGraphRegistry
//      */
//     JoinerQueryBase<T, R> joinGraphs(Enum... names);
// 
//     /**
//      * Add join graphs to the query.
//      *
//      * @param names names of join graphs
//      * @return this
//      * @see cz.encircled.joiner.query.join.JoinGraphRegistry
//      */
//     JoinerQueryBase<T, R> joinGraphs(Collection<?> names);
// 
//     Set<Object> getJoinGraphs();
// 
//     /**
//      * Add <b>left</b> joins for specified paths
//      *
//      * @param paths join paths
//      * @return this
//      */
//     JoinerQueryBase<T, R> joins(EntityPath<?>... paths);
// 
//     JoinerQueryBase<T, R> joins(CollectionPathBase<?, ?, ?>... path);
// 
//     JoinerQueryBase<T, R> joins(JoinDescription... joins);
// 
//     JoinerQueryBase<T, R> joins(Collection<JoinDescription> joins);
// 
//     Collection<JoinDescription> getJoins();
// 
//     JoinerQueryBase<T, R> addHint(String hint, Object value);
// 
//     LinkedHashMap<String, List<Object>> getHints();
// 
//     JoinerQueryBase<T, R> addFeatures(QueryFeature... features);
// 
//     JoinerQueryBase<T, R> addFeatures(Collection<QueryFeature> features);
// 
//     List<QueryFeature> getFeatures();
// 
//     /**
//      * Set offset for the query results
//      *
//      * @param offset value
//      * @return this
//      */
//     JoinerQuery<T, R> offset(Long offset);
// 
//     Long getOffset();
// 
//     /**
//      * Set max results for the query results
//      *
//      * @param limit value
//      * @return this
//      */
//     JoinerQuery<T, R> limit(Long limit);
// 
//     Long getLimit();
// 
//     JoinerQuery<T, R> asc(Expression<?> orderBy);
// 
//     JoinerQuery<T, R> desc(Expression<?> orderBy);
// 
//     List<QueryOrder> getOrder();
// 
//     JoinerQuery<T, R> copy();
// 
//     boolean isCount();
// 
// }
// 
// Path: joiner-core/src/main/java/cz/encircled/joiner/query/QueryFeature.java
// public interface QueryFeature {
// 
//     /**
//      * This method is called before JPA query creation and allows request modification
//      *
//      * @param request initial joiner request
//      * @param <T>     query from
//      * @param <R>     query return type
//      * @return modified request
//      */
//     <T, R> JoinerQuery<T, R> before(JoinerQuery<T, R> request);
// 
//     /**
//      * This method is called just before JPA query execution and allows to modify result query directly
//      *
//      * @param request initial joiner request
//      * @param query   JPA query
//      * @return modified JPA query to be executed
//      */
//     default <T, R> ExtendedJPAQuery<R> after(JoinerQuery<T, R> request, ExtendedJPAQuery<R> query) {
//         return query;
//     }
// 
// }


import com.google.common.collect.Multimap;
import com.querydsl.jpa.impl.AbstractJPAQuery;
import cz.encircled.joiner.core.TestException;
import cz.encircled.joiner.query.ExtendedJPAQuery;
import cz.encircled.joiner.query.JoinerQuery;
import cz.encircled.joiner.query.QueryFeature;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.Collection;
package cz.encircled.joiner.config.hint;



/**
 * @author Kisel on 04.02.2016.
 */
public class HintQueryFeature implements QueryFeature {

    @Override
    public <T, R> JoinerQuery<T, R> before(final JoinerQuery<T, R> request) {
        return request;
    }

    @Override
// Path: joiner-core/src/test/java/cz/encircled/joiner/core/TestException.java
// public class TestException extends RuntimeException {
// }
// 
// Path: joiner-core/src/main/java/cz/encircled/joiner/query/ExtendedJPAQuery.java
// public class ExtendedJPAQuery<T> extends JPAQuery<T> {
// 
//     public ExtendedJPAQuery(EntityManager entityManager, JPAQuery<T> another) {
//         super(entityManager, another.getMetadata().clone());
//         clone(another);
//     }
// 
//     public JPQLSerializer getSerializer(boolean forCount) {
//         return serialize(forCount);
//     }
// 
// }
// 
// Path: joiner-core/src/main/java/cz/encircled/joiner/query/JoinerQuery.java
// public interface JoinerQuery<T, R> extends JoinRoot {
// 
//     EntityPath<T> getFrom();
// 
//     Expression<R> getReturnProjection();
// 
//     JoinerQuery<T, R> where(Predicate where);
// 
//     Predicate getWhere();
// 
//     JoinerQuery<T, R> distinct(boolean isDistinct);
// 
//     boolean isDistinct();
// 
//     JoinerQuery<T, R> groupBy(Path<?> groupBy);
// 
//     Path<?> getGroupBy();
// 
//     JoinerQuery<T, R> having(Predicate having);
// 
//     Predicate getHaving();
// 
//     /**
//      * Add join graphs to the query.
//      *
//      * @param names names of join graphs
//      * @return this
//      * @see cz.encircled.joiner.query.join.JoinGraphRegistry
//      */
//     JoinerQuery<T, R> joinGraphs(String... names);
// 
//     /**
//      * Add join graphs to the query.
//      *
//      * @param names names of join graphs
//      * @return this
//      * @see cz.encircled.joiner.query.join.JoinGraphRegistry
//      */
//     JoinerQueryBase<T, R> joinGraphs(Enum... names);
// 
//     /**
//      * Add join graphs to the query.
//      *
//      * @param names names of join graphs
//      * @return this
//      * @see cz.encircled.joiner.query.join.JoinGraphRegistry
//      */
//     JoinerQueryBase<T, R> joinGraphs(Collection<?> names);
// 
//     Set<Object> getJoinGraphs();
// 
//     /**
//      * Add <b>left</b> joins for specified paths
//      *
//      * @param paths join paths
//      * @return this
//      */
//     JoinerQueryBase<T, R> joins(EntityPath<?>... paths);
// 
//     JoinerQueryBase<T, R> joins(CollectionPathBase<?, ?, ?>... path);
// 
//     JoinerQueryBase<T, R> joins(JoinDescription... joins);
// 
//     JoinerQueryBase<T, R> joins(Collection<JoinDescription> joins);
// 
//     Collection<JoinDescription> getJoins();
// 
//     JoinerQueryBase<T, R> addHint(String hint, Object value);
// 
//     LinkedHashMap<String, List<Object>> getHints();
// 
//     JoinerQueryBase<T, R> addFeatures(QueryFeature... features);
// 
//     JoinerQueryBase<T, R> addFeatures(Collection<QueryFeature> features);
// 
//     List<QueryFeature> getFeatures();
// 
//     /**
//      * Set offset for the query results
//      *
//      * @param offset value
//      * @return this
//      */
//     JoinerQuery<T, R> offset(Long offset);
// 
//     Long getOffset();
// 
//     /**
//      * Set max results for the query results
//      *
//      * @param limit value
//      * @return this
//      */
//     JoinerQuery<T, R> limit(Long limit);
// 
//     Long getLimit();
// 
//     JoinerQuery<T, R> asc(Expression<?> orderBy);
// 
//     JoinerQuery<T, R> desc(Expression<?> orderBy);
// 
//     List<QueryOrder> getOrder();
// 
//     JoinerQuery<T, R> copy();
// 
//     boolean isCount();
// 
// }
// 
// Path: joiner-core/src/main/java/cz/encircled/joiner/query/QueryFeature.java
// public interface QueryFeature {
// 
//     /**
//      * This method is called before JPA query creation and allows request modification
//      *
//      * @param request initial joiner request
//      * @param <T>     query from
//      * @param <R>     query return type
//      * @return modified request
//      */
//     <T, R> JoinerQuery<T, R> before(JoinerQuery<T, R> request);
// 
//     /**
//      * This method is called just before JPA query execution and allows to modify result query directly
//      *
//      * @param request initial joiner request
//      * @param query   JPA query
//      * @return modified JPA query to be executed
//      */
//     default <T, R> ExtendedJPAQuery<R> after(JoinerQuery<T, R> request, ExtendedJPAQuery<R> query) {
//         return query;
//     }
// 
// }


// Path: joiner-core/src/test/java/cz/encircled/joiner/config/hint/HintQueryFeature.java
import com.google.common.collect.Multimap;
import com.querydsl.jpa.impl.AbstractJPAQuery;
import cz.encircled.joiner.core.TestException;
import cz.encircled.joiner.query.ExtendedJPAQuery;
import cz.encircled.joiner.query.JoinerQuery;
import cz.encircled.joiner.query.QueryFeature;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.Collection;

package cz.encircled.joiner.config.hint;



/**
 * @author Kisel on 04.02.2016.
 */
public class HintQueryFeature implements QueryFeature {

    @Override
    public <T, R> JoinerQuery<T, R> before(final JoinerQuery<T, R> request) {
        return request;
    }

    @Override
    public <T, R> ExtendedJPAQuery<R> after(JoinerQuery<T, R> request, ExtendedJPAQuery<R> query) {