<commit_before>/*
 * Copyright (c) 2007-2008, Hazel Ltd. All Rights Reserved.
 *
 * 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
 * limitations under the License.
 *
 */

package com.hazelcast.query;

import com.hazelcast.core.MapEntry;
import com.hazelcast.nio.DataSerializable;
import com.hazelcast.nio.SerializationHelper;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Predicates {

    public static class GreaterLessPredicate extends EqualPredicate {
        boolean equal = false;
        boolean less = false;

        public GreaterLessPredicate() {
        }

        public GreaterLessPredicate(Expression first, Expression second, boolean equal, boolean less) {
            super(first, second);
            this.equal = equal;
            this.less = less;
        }

        public GreaterLessPredicate(Expression first, Object second, boolean equal, boolean less) {
            super(first, second);
            this.equal = equal;
            this.less = less;
        }

        public boolean apply(MapEntry entry) {
            int expectedResult = (less) ? -1 : 1;
            Expression<Comparable> cFirst = (Expression<Comparable>) first;
            int result;
            if (secondIsExpression) {
                result = cFirst.getValue(entry).compareTo(((Expression) second).getValue(entry));
            } else {
                result = cFirst.getValue(entry).compareTo(second);
            }
            if (equal && result == 0) return true;
            return (expectedResult == result);
        }

        public Set<MapEntry> filter(Map<Expression, Index<MapEntry>> namedIndexes) {
            Index index = namedIndexes.get(first);
            return index.getSubRecords(equal, less, index.getLongValue(second));
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(first);
            sb.append(less ? "<" : ">");
            sb.append(equal ? "=" : "");
            sb.append(second);
            return sb.toString();
        }
    }

    public static class BetweenPredicate extends EqualPredicate {
        Object to;

        public BetweenPredicate() {
        }

        public BetweenPredicate(Expression first, Expression from, Object to) {
            super(first, from);
            this.to = to;
        }

        public BetweenPredicate(Expression first, Object from, Object to) {
            super(first, from);
            this.to = to;
        }

        public boolean apply(MapEntry entry) {
            Expression<Comparable> cFirst = (Expression<Comparable>) first;
            Comparable firstValue = cFirst.getValue(entry);
            Comparable fromValue = (Comparable) second;
            Comparable toValue = (Comparable) to;
            if (firstValue == null || fromValue == null || toValue == null) return false;
            return firstValue.compareTo(fromValue) >= 0 && firstValue.compareTo(toValue) <= 0;
        }

        public Set<MapEntry> filter(Map<Expression, Index<MapEntry>> namedIndexes) {
            Index index = namedIndexes.get(first);
            return index.getSubRecords(index.getLongValue(second), index.getLongValue(to));
        }

        public void writeData(DataOutput out) throws IOException {
            super.writeData(out);
            writeObject(out, to);
        }

        public void readData(DataInput in) throws IOException {
            super.readData(in);
            to = readObject(in);
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(first);
            sb.append(" BETWEEN ");
            sb.append(second);
            sb.append(" AND ");
            sb.append(to);
            return sb.toString();
        }
    }

    public static class NotEqualPredicate extends EqualPredicate {
        public NotEqualPredicate() {
        }

        public NotEqualPredicate(Expression first, Expression second) {
            super(first, second);
        }

        public NotEqualPredicate(Expression first, Object second) {
            super(first, second);
        }

        public boolean apply(MapEntry entry) {
            return !super.apply(entry);
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(first);
            sb.append("!=");
            sb.append(second);
            return sb.toString();
        }
    }

    public static class NotPredicate extends AbstractPredicate {
        Predicate predicate;

        public NotPredicate(Predicate predicate) {
            this.predicate = predicate;
        }

        public NotPredicate() {
        }

        public boolean apply(MapEntry mapEntry) {
            return !predicate.apply(mapEntry);
        }

        public void writeData(DataOutput out) throws IOException {
            writeObject(out, predicate);
        }

        public void readData(DataInput in) throws IOException {
            predicate = (Predicate) readObject(in);
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append("NOT(");
            sb.append(predicate.toString());
            sb.append(")");
            return sb.toString();
        }
    }

    public static class InPredicate extends AbstractPredicate implements IndexAwarePredicate {
        Expression first;
        Object[] values = null;
        Object[] convertedValues = null;

        public InPredicate() {
        }

        public InPredicate(Expression first, Object... second) {
            this.first = first;
            this.values = second;
        }

        public boolean apply(MapEntry entry) {
            Object firstVal = first.getValue(entry);
            if (firstVal == null) return false;
            if (convertedValues != null) {
                return in(firstVal, convertedValues);
            } else {
                if (firstVal.getClass() == values[0].getClass()) {
                    return in(firstVal, values);
                } else if (values[0] instanceof String) {
                    convertedValues = new Object[values.length];
                    for (int i = 0; i < values.length; i++) {
                        convertedValues[i] = getRealObject(firstVal.getClass(), (String) values[i]);
                    }
                    return in(firstVal, convertedValues);
                }
            }
            return in(firstVal, values);
        }

        private boolean in(Object firstVal, Object[] values) {
            for (Object o : values) {
                if (firstVal.equals(o)) return true;
            }
            return false;
        }

        public boolean collectIndexAwarePredicates(List<IndexAwarePredicate> lsIndexPredicates, Map<Expression, Index<MapEntry>> mapIndexes) {
            if (first instanceof GetExpression) {
                Index index = mapIndexes.get(first);
                if (index != null) {
                    lsIndexPredicates.add(this);
                } else {
                    return false;
                }
            }
            return true;
        }

        public void collectAppliedIndexes(Set<Index> setAppliedIndexes, Map<Expression, Index<MapEntry>> mapIndexes) {
            Index index = mapIndexes.get(first);
            if (index != null) {
                setAppliedIndexes.add(index);
            }
        }

        public Set<MapEntry> filter(Map<Expression, Index<MapEntry>> mapIndexes) {
            Index index = mapIndexes.get(first);
            if (index != null) {
                long[] longValues = new long[values.length];
                for (int i = 0; i < values.length; i++) {
                    longValues[i] = index.getLongValue(values[i]);
                }
                return index.getRecords(longValues);
            } else {
                return null;
            }
        }

        public Object getValue() {
            return values;
        }

        public void writeData(DataOutput out) throws IOException {
            writeObject(out, first);
            out.writeInt(values.length);
            for (int i = 0; i < values.length; i++) {
                writeObject(out, values[i]);
            }
        }

        public void readData(DataInput in) throws IOException {
            try {
                first = (Expression) readObject(in);
                int len = in.readInt();
                values = new Object[len];
                for (int i = 0; i < values.length; i++) {
                    values[i] = readObject(in);
                }
            } catch (Exception e) {
                throw new IOException(e.getMessage());
            }
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(first);
            sb.append(" IN (");
            for (int i = 0; i < values.length; i++) {
                sb.append(values[i]);
                if (i < (values.length - 1)) {
                    sb.append(",");
                }
            }
            sb.append(")");
            return sb.toString();
        }
    }

    public static class LikePredicate extends AbstractPredicate {
        Expression<String> first;
        String second;
        Pattern pattern = null;

        public LikePredicate() {
        }

        public LikePredicate(Expression<String> first, String second) {
            this.first = first;
            char lastChar = second.charAt(second.length()-1);
            if (lastChar != '\'') {
                String replacer = "hz#" + lastChar;
                second = second.substring(0, second.lastIndexOf('\'')+1).replaceAll(replacer, " ");
            }
            this.second = second;
            second = second.replaceAll("%", ".*").replaceAll("_", ".");
            pattern = Pattern.compile(second);
        }<commit_msg>Fix for the query LIKE<commit_after>/*
 * Copyright (c) 2007-2008, Hazel Ltd. All Rights Reserved.
 *
 * 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
 * limitations under the License.
 *
 */

package com.hazelcast.query;

import com.hazelcast.core.MapEntry;
import com.hazelcast.nio.DataSerializable;
import com.hazelcast.nio.SerializationHelper;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Predicates {

    public static class GreaterLessPredicate extends EqualPredicate {
        boolean equal = false;
        boolean less = false;

        public GreaterLessPredicate() {
        }

        public GreaterLessPredicate(Expression first, Expression second, boolean equal, boolean less) {
            super(first, second);
            this.equal = equal;
            this.less = less;
        }

        public GreaterLessPredicate(Expression first, Object second, boolean equal, boolean less) {
            super(first, second);
            this.equal = equal;
            this.less = less;
        }

        public boolean apply(MapEntry entry) {
            int expectedResult = (less) ? -1 : 1;
            Expression<Comparable> cFirst = (Expression<Comparable>) first;
            int result;
            if (secondIsExpression) {
                result = cFirst.getValue(entry).compareTo(((Expression) second).getValue(entry));
            } else {
                result = cFirst.getValue(entry).compareTo(second);
            }
            if (equal && result == 0) return true;
            return (expectedResult == result);
        }

        public Set<MapEntry> filter(Map<Expression, Index<MapEntry>> namedIndexes) {
            Index index = namedIndexes.get(first);
            return index.getSubRecords(equal, less, index.getLongValue(second));
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(first);
            sb.append(less ? "<" : ">");
            sb.append(equal ? "=" : "");
            sb.append(second);
            return sb.toString();
        }
    }

    public static class BetweenPredicate extends EqualPredicate {
        Object to;

        public BetweenPredicate() {
        }

        public BetweenPredicate(Expression first, Expression from, Object to) {
            super(first, from);
            this.to = to;
        }

        public BetweenPredicate(Expression first, Object from, Object to) {
            super(first, from);
            this.to = to;
        }

        public boolean apply(MapEntry entry) {
            Expression<Comparable> cFirst = (Expression<Comparable>) first;
            Comparable firstValue = cFirst.getValue(entry);
            Comparable fromValue = (Comparable) second;
            Comparable toValue = (Comparable) to;
            if (firstValue == null || fromValue == null || toValue == null) return false;
            return firstValue.compareTo(fromValue) >= 0 && firstValue.compareTo(toValue) <= 0;
        }

        public Set<MapEntry> filter(Map<Expression, Index<MapEntry>> namedIndexes) {
            Index index = namedIndexes.get(first);
            return index.getSubRecords(index.getLongValue(second), index.getLongValue(to));
        }

        public void writeData(DataOutput out) throws IOException {
            super.writeData(out);
            writeObject(out, to);
        }

        public void readData(DataInput in) throws IOException {
            super.readData(in);
            to = readObject(in);
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(first);
            sb.append(" BETWEEN ");
            sb.append(second);
            sb.append(" AND ");
            sb.append(to);
            return sb.toString();
        }
    }

    public static class NotEqualPredicate extends EqualPredicate {
        public NotEqualPredicate() {
        }

        public NotEqualPredicate(Expression first, Expression second) {
            super(first, second);
        }

        public NotEqualPredicate(Expression first, Object second) {
            super(first, second);
        }

        public boolean apply(MapEntry entry) {
            return !super.apply(entry);
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(first);
            sb.append("!=");
            sb.append(second);
            return sb.toString();
        }
    }

    public static class NotPredicate extends AbstractPredicate {
        Predicate predicate;

        public NotPredicate(Predicate predicate) {
            this.predicate = predicate;
        }

        public NotPredicate() {
        }

        public boolean apply(MapEntry mapEntry) {
            return !predicate.apply(mapEntry);
        }

        public void writeData(DataOutput out) throws IOException {
            writeObject(out, predicate);
        }

        public void readData(DataInput in) throws IOException {
            predicate = (Predicate) readObject(in);
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append("NOT(");
            sb.append(predicate.toString());
            sb.append(")");
            return sb.toString();
        }
    }

    public static class InPredicate extends AbstractPredicate implements IndexAwarePredicate {
        Expression first;
        Object[] values = null;
        Object[] convertedValues = null;

        public InPredicate() {
        }

        public InPredicate(Expression first, Object... second) {
            this.first = first;
            this.values = second;
        }

        public boolean apply(MapEntry entry) {
            Object firstVal = first.getValue(entry);
            if (firstVal == null) return false;
            if (convertedValues != null) {
                return in(firstVal, convertedValues);
            } else {
                if (firstVal.getClass() == values[0].getClass()) {
                    return in(firstVal, values);
                } else if (values[0] instanceof String) {
                    convertedValues = new Object[values.length];
                    for (int i = 0; i < values.length; i++) {
                        convertedValues[i] = getRealObject(firstVal.getClass(), (String) values[i]);
                    }
                    return in(firstVal, convertedValues);
                }
            }
            return in(firstVal, values);
        }

        private boolean in(Object firstVal, Object[] values) {
            for (Object o : values) {
                if (firstVal.equals(o)) return true;
            }
            return false;
        }

        public boolean collectIndexAwarePredicates(List<IndexAwarePredicate> lsIndexPredicates, Map<Expression, Index<MapEntry>> mapIndexes) {
            if (first instanceof GetExpression) {
                Index index = mapIndexes.get(first);
                if (index != null) {
                    lsIndexPredicates.add(this);
                } else {
                    return false;
                }
            }
            return true;
        }

        public void collectAppliedIndexes(Set<Index> setAppliedIndexes, Map<Expression, Index<MapEntry>> mapIndexes) {
            Index index = mapIndexes.get(first);
            if (index != null) {
                setAppliedIndexes.add(index);
            }
        }

        public Set<MapEntry> filter(Map<Expression, Index<MapEntry>> mapIndexes) {
            Index index = mapIndexes.get(first);
            if (index != null) {
                long[] longValues = new long[values.length];
                for (int i = 0; i < values.length; i++) {
                    longValues[i] = index.getLongValue(values[i]);
                }
                return index.getRecords(longValues);
            } else {
                return null;
            }
        }

        public Object getValue() {
            return values;
        }

        public void writeData(DataOutput out) throws IOException {
            writeObject(out, first);
            out.writeInt(values.length);
            for (int i = 0; i < values.length; i++) {
                writeObject(out, values[i]);
            }
        }

        public void readData(DataInput in) throws IOException {
            try {
                first = (Expression) readObject(in);
                int len = in.readInt();
                values = new Object[len];
                for (int i = 0; i < values.length; i++) {
                    values[i] = readObject(in);
                }
            } catch (Exception e) {
                throw new IOException(e.getMessage());
            }
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(first);
            sb.append(" IN (");
            for (int i = 0; i < values.length; i++) {
                sb.append(values[i]);
                if (i < (values.length - 1)) {
                    sb.append(",");
                }
            }
            sb.append(")");
            return sb.toString();
        }
    }

    public static class LikePredicate extends AbstractPredicate {
        Expression<String> first;
        String second;
        Pattern pattern = null;

        public LikePredicate() {
        }

        public LikePredicate(Expression<String> first, String second) {
            this.first = first;
            char firstChar = second.charAt(0);
            char lastChar = second.charAt(second.length()-1);
            if (firstChar == '\'' && lastChar != '\'') {
                String replacer = "hz#" + lastChar;
                second = second.substring(0, second.lastIndexOf('\'')+1).replaceAll(replacer, " ");
            }
            this.second = second;
            second = second.replaceAll("%", ".*").replaceAll("_", ".");
            pattern = Pattern.compile(second);
        }
{'fraction_non_alphanumeric': 0.10107048519393855, 'fraction_numerical': 0.0026414569720561655, 'mean_word_length': 1.764185986934802, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2367225', 'n_tokens_mistral': 5547, 'n_tokens_neox': 5339, 'n_words': 1430}