package net.kaleidos.hibernate.criterion.array;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.engine.TypedValue;
import org.hibernate.type.Type;
import org.hibernate.util.StringHelper;

/**
 * Constrains a property in an array
 */
public class PgArrayExpression implements Criterion {

    private static final long serialVersionUID = 2872183637309166619L;

    private final PgCriteriaUtils pgCriteriaUtils = new PgCriteriaUtils();

    private final String propertyName;
    private final Object value;
    private final String op;

    protected PgArrayExpression(String propertyName, Object value, String op) {
        this.propertyName = propertyName;
        this.value = value;
        this.op = op;
    }

    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        return StringHelper.join(
            " and ",
            StringHelper.suffix(criteriaQuery.findColumns(propertyName, criteria), " " + op + " ARRAY[?]")
        );
    }

    @Override
    public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        Type propertyType = criteriaQuery.getType(criteria, propertyName);
        String propertyTypeName = propertyType.getName();

        Object[] arrValue;
        if ("net.kaleidos.hibernate.usertype.IntegerArrayType".equals(propertyTypeName)) {
            arrValue = pgCriteriaUtils.getValueAsArrayOfType(value, Integer.class);
        } else if ("net.kaleidos.hibernate.usertype.LongArrayType".equals(propertyTypeName)) {
            arrValue = pgCriteriaUtils.getValueAsArrayOfType(value, Long.class);
        } else if ("net.kaleidos.hibernate.usertype.StringArrayType".equals(propertyTypeName)) {
            arrValue = pgCriteriaUtils.getValueAsArrayOfType(value, String.class);
        } else {
            throw new HibernateException("Native array for this type is not supported");
        }

        return new TypedValue[] {
            criteriaQuery.getTypedValue(criteria, propertyName, arrValue)
        };
    }
}
@@ -315,16 +315,72 @@
 elper;%0A%0A
+import java.lang.reflect.Array;%0Aimport java.util.List;%0A%0A
 /**%0A * C
@@ -1642,32 +1642,657 @@
 Integer.class);%0A
+        %7D else if (%22net.kaleidos.hibernate.usertype.IdentityEnumArrayType%22.equals(propertyTypeName)) %7B%0A            if (value instanceof List) %7B%0A                List valueAsList = (List)value;%0A                arrValue = (Object%5B%5D) Array.newInstance(Integer.class, valueAsList.size());%0A%0A                for(int i=0; i %3C valueAsList.size(); i++) %7B%0A                    arrValue%5Bi%5D = ((Enum)(valueAsList.get(i))).ordinal();%0A                %7D%0A            %7D else %7B%0A                Object converted = ((Enum)value).ordinal();%0A                arrValue = pgCriteriaUtils.getValueAsArrayOfType(converted, Integer.class);%0A            %7D%0A%0A
         %7D else i

Properly convert IdentityEnumArrayType values for CriteriaQueries