// Path: src/main/java/com/eharmony/pho/query/criterion/Criterion.java
// public interface Criterion {
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/GroupCriterion.java
// public interface GroupCriterion  extends Criterion{
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/Orderings.java
// public class Orderings {
// 
//     private final List<Ordering> orderings = new ArrayList<Ordering>();
// 
//     public Orderings() {
//     }
// 
//     public Orderings(Ordering... orderings) {
//         this.orderings.addAll(Arrays.asList(orderings));
//     }
// 
//     public void add(Ordering ordering) {
//         orderings.add(ordering);
//     }
// 
//     // Discuss: defensive copy?
//     public List<Ordering> get() {
//         return orderings;
//     }
// 
//     @Override
//     public String toString() {
//         return "Orderings [" + orderings + "]";
//     }
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/projection/Projection.java
// public class Projection implements Criterion, WithAggregateFunction {
//     private final Aggregate function;
//     private final List<String> propertyNames;
// 
//     protected Projection(Aggregate function, String... propertyNames) {
//         this.function = function;
//         this.propertyNames = Arrays.asList(propertyNames);
//     }
// 
//     @Override
//     public Aggregate getAggregate() {
//         return this.function;
//     }
// 
//     public List<String> getPropertyNames() {
//         return this.propertyNames;
//     }
// }


import java.util.List;
import com.eharmony.pho.query.criterion.Criterion;
import com.eharmony.pho.query.criterion.GroupCriterion;
import com.eharmony.pho.query.criterion.Orderings;
import com.eharmony.pho.query.criterion.projection.Projection;
package com.eharmony.pho.query;



/**
 * A generic, object oriented representation of a query
 * 
 * @param <T>
 *            the entity type being queried
 * @param <R>
 *            the desired return type
 */
public interface QuerySelect<T, R> {

    /**
     * Get the queried entity type.
     * 
     * @return the entity class being queried
     */
    public Class<T> getEntityClass();

    /**
     * Get the return entity type.
     * 
     * @return the class of the desired return type
     */
    public Class<R> getReturnType();

    /**
     * The list of properties to return. An empty collection means all properties.
     * 
     * @return the fields to be returned from the query
     */
    public List<String> getReturnFields();

    /**
     * Get the query criteria. The top level object can either be a single Criterion or a Junction of multiple nested
     * Criterion objects.
     * 
     * @return the root criterion node
     */
    public Criterion getCriteria();

    Criterion getGroupCriteria();

    /**
     * Get the Order clauses.
     * 
     * @return the ordering clauses
     */
    public Orderings getOrder();

    public List<Projection> getProjection();

    /**
     * Get the max desired results. Null signifies no maximum.
     * 
     * @return the maximum number of results or null if no maximum
     * 
     */
// Path: src/main/java/com/eharmony/pho/query/criterion/Criterion.java
// public interface Criterion {
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/GroupCriterion.java
// public interface GroupCriterion  extends Criterion{
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/Orderings.java
// public class Orderings {
// 
//     private final List<Ordering> orderings = new ArrayList<Ordering>();
// 
//     public Orderings() {
//     }
// 
//     public Orderings(Ordering... orderings) {
//         this.orderings.addAll(Arrays.asList(orderings));
//     }
// 
//     public void add(Ordering ordering) {
//         orderings.add(ordering);
//     }
// 
//     // Discuss: defensive copy?
//     public List<Ordering> get() {
//         return orderings;
//     }
// 
//     @Override
//     public String toString() {
//         return "Orderings [" + orderings + "]";
//     }
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/projection/Projection.java
// public class Projection implements Criterion, WithAggregateFunction {
//     private final Aggregate function;
//     private final List<String> propertyNames;
// 
//     protected Projection(Aggregate function, String... propertyNames) {
//         this.function = function;
//         this.propertyNames = Arrays.asList(propertyNames);
//     }
// 
//     @Override
//     public Aggregate getAggregate() {
//         return this.function;
//     }
// 
//     public List<String> getPropertyNames() {
//         return this.propertyNames;
//     }
// }


// Path: src/main/java/com/eharmony/pho/query/QuerySelect.java
import java.util.List;
import com.eharmony.pho.query.criterion.Criterion;
import com.eharmony.pho.query.criterion.GroupCriterion;
import com.eharmony.pho.query.criterion.Orderings;
import com.eharmony.pho.query.criterion.projection.Projection;

package com.eharmony.pho.query;



/**
 * A generic, object oriented representation of a query
 * 
 * @param <T>
 *            the entity type being queried
 * @param <R>
 *            the desired return type
 */
public interface QuerySelect<T, R> {

    /**
     * Get the queried entity type.
     * 
     * @return the entity class being queried
     */
    public Class<T> getEntityClass();

    /**
     * Get the return entity type.
     * 
     * @return the class of the desired return type
     */
    public Class<R> getReturnType();

    /**
     * The list of properties to return. An empty collection means all properties.
     * 
     * @return the fields to be returned from the query
     */
    public List<String> getReturnFields();

    /**
     * Get the query criteria. The top level object can either be a single Criterion or a Junction of multiple nested
     * Criterion objects.
     * 
     * @return the root criterion node
     */
    public Criterion getCriteria();

    Criterion getGroupCriteria();

    /**
     * Get the Order clauses.
     * 
     * @return the ordering clauses
     */
    public Orderings getOrder();

    public List<Projection> getProjection();

    /**
     * Get the max desired results. Null signifies no maximum.
     * 
     * @return the maximum number of results or null if no maximum
     * 
     */
    public Integer getMaxResults();