// Path: src/main/java/com/eharmony/pho/query/criterion/Criterion.java
// public interface Criterion {
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/Operator.java
// public enum Operator implements Symbolic {
//     EQUAL("="), NOT_EQUAL("!="), GREATER_THAN(">"), GREATER_THAN_OR_EQUAL(">="), LESS_THAN("<"), LESS_THAN_OR_EQUAL(
//             "<="),
// 
//     BETWEEN("between"),
//     
//     LIKE("like"), ILIKE("ilike"),
// 
//     NULL("null"), NOT_NULL("not null"), EMPTY("empty"), NOT_EMPTY("not empty"),
// 
//     IN("in"), NOT_IN("not in"), CONTAINS("contains"),
// 
//     WITHIN("within"),
// 
//     AND("and"), OR("or");
// 
//     private final String symbol;
//     private static final ImmutableMap<String, Operator> map = SymbolicLookup.map(values());
// 
//     private Operator(String symbol) {
//         this.symbol = symbol;
//     }
// 
//     @Override
//     public String symbol() {
//         return symbol;
//     }
// 
//     public static Operator fromString(String val) {
//         return SymbolicLookup.resolve(val, map, Operator.class);
//     }
// 
//     @Override
//     public String toString() {
//         return symbol();
//     }
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/WithOperator.java
// public interface WithOperator {
// 
//     public Operator getOperator();
// 
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/WithProperty.java
// public interface WithProperty {
// 
//     public String getPropertyName();
// 
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/projection/AggregateProjection.java
// public class AggregateProjection extends Projection {
//     private String propertyName;
//     private Aggregate function;
// 
//     protected AggregateProjection(Aggregate function, String propertyName) {
//         super(function, propertyName);
//         this.propertyName = propertyName;
//         this.function = function;
//     }
// 
//     public String getPropertyName(){
//         return propertyName;
//     }
// 
//     public AggregateProjection setPropertyName(String propertyName) {
//         this.propertyName = propertyName;
//         return this;
//     }
// 
//     public String getName() {
//         return function.symbol() + "(" + propertyName + ")";
//     }
// }


import com.eharmony.pho.query.criterion.Criterion;
import com.eharmony.pho.query.criterion.Operator;
import com.eharmony.pho.query.criterion.WithOperator;
import com.eharmony.pho.query.criterion.WithProperty;
import com.eharmony.pho.query.criterion.projection.AggregateProjection;
package com.eharmony.pho.query.criterion.expression;


/**
 * An abstract expression with an operator that acts on a property name.
 */
public abstract class Expression implements Criterion, WithOperator, WithProperty {

    private final Operator operator;
    private final String propertyName;
    private final AggregateProjection aggregateProjection;

    protected Expression(Operator operator, String propertyName, AggregateProjection aggregateProjection) {
        this.operator = operator;
        this.propertyName = propertyName;
        this.aggregateProjection = aggregateProjection;
    }

// Path: src/main/java/com/eharmony/pho/query/criterion/Criterion.java
// public interface Criterion {
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/Operator.java
// public enum Operator implements Symbolic {
//     EQUAL("="), NOT_EQUAL("!="), GREATER_THAN(">"), GREATER_THAN_OR_EQUAL(">="), LESS_THAN("<"), LESS_THAN_OR_EQUAL(
//             "<="),
// 
//     BETWEEN("between"),
//     
//     LIKE("like"), ILIKE("ilike"),
// 
//     NULL("null"), NOT_NULL("not null"), EMPTY("empty"), NOT_EMPTY("not empty"),
// 
//     IN("in"), NOT_IN("not in"), CONTAINS("contains"),
// 
//     WITHIN("within"),
// 
//     AND("and"), OR("or");
// 
//     private final String symbol;
//     private static final ImmutableMap<String, Operator> map = SymbolicLookup.map(values());
// 
//     private Operator(String symbol) {
//         this.symbol = symbol;
//     }
// 
//     @Override
//     public String symbol() {
//         return symbol;
//     }
// 
//     public static Operator fromString(String val) {
//         return SymbolicLookup.resolve(val, map, Operator.class);
//     }
// 
//     @Override
//     public String toString() {
//         return symbol();
//     }
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/WithOperator.java
// public interface WithOperator {
// 
//     public Operator getOperator();
// 
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/WithProperty.java
// public interface WithProperty {
// 
//     public String getPropertyName();
// 
// }
// 
// Path: src/main/java/com/eharmony/pho/query/criterion/projection/AggregateProjection.java
// public class AggregateProjection extends Projection {
//     private String propertyName;
//     private Aggregate function;
// 
//     protected AggregateProjection(Aggregate function, String propertyName) {
//         super(function, propertyName);
//         this.propertyName = propertyName;
//         this.function = function;
//     }
// 
//     public String getPropertyName(){
//         return propertyName;
//     }
// 
//     public AggregateProjection setPropertyName(String propertyName) {
//         this.propertyName = propertyName;
//         return this;
//     }
// 
//     public String getName() {
//         return function.symbol() + "(" + propertyName + ")";
//     }
// }


// Path: src/main/java/com/eharmony/pho/query/criterion/expression/Expression.java
import com.eharmony.pho.query.criterion.Criterion;
import com.eharmony.pho.query.criterion.Operator;
import com.eharmony.pho.query.criterion.WithOperator;
import com.eharmony.pho.query.criterion.WithProperty;
import com.eharmony.pho.query.criterion.projection.AggregateProjection;

package com.eharmony.pho.query.criterion.expression;


/**
 * An abstract expression with an operator that acts on a property name.
 */
public abstract class Expression implements Criterion, WithOperator, WithProperty {

    private final Operator operator;
    private final String propertyName;
    private final AggregateProjection aggregateProjection;

    protected Expression(Operator operator, String propertyName, AggregateProjection aggregateProjection) {
        this.operator = operator;
        this.propertyName = propertyName;
        this.aggregateProjection = aggregateProjection;
    }

    protected Expression(Operator operator, String propertyName) {