All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.moengage.evaluator.ConditionEvaluator Maven / Gradle / Ivy

package com.moengage.evaluator;

import com.moengage.enum_models.FilterOperator;
import com.moengage.enum_models.FilterParameter;
import com.moengage.enum_models.FilterType;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.regex.*;

import java.util.TimeZone;


public class ConditionEvaluator {
    protected JSONObject filterCondition;
    protected JSONObject filters;
    protected TimeZone appTimeZone;

    /**
     * ConditionEvaluator takes conditions and filters and returns whether the filters satisfy the condition or not
     *
     * @param filterCondition The filter condition object. The sample structure is given below
     *                        condition = {
     *                        filter_operator: "and"
     *                        filters: [
     *                        {
     *                        name: "u_mb",
     *                        operator: "is",
     *                        value: "9898989989",
     *                        data_type: "string",
     *                        "negate": true,
     *                        "case_sensitive": false
     *                        },
     *                        {
     *                        "operator": "lessThan",
     *                        "data_type": "datetime",
     *                        "name": "u_l_a",
     *                        "value": "2015-07-30T00:00:00"
     *                        },
     *                        ]
     *                        }
     * @param filters         The action attribute filters done by the user or user properties, sample given below
     *                        filters = {
     *                        u_mb: "8887776665",
     *                        u_l_a: "2015-07-30T08:33:54,
     *                        u_n: "moengage",
     *                        u_em: "[email protected]",
     *                        age: 3
     *                        }
     *                        url for reference :
     *                        https://github.com/moengage/commons/blob/master/moengage/commons/attrs/config/config.json
     */

    public ConditionEvaluator(JSONObject filterCondition, JSONObject filters, TimeZone appTimeZone) {
        this.filterCondition = filterCondition;
        this.filters = filters;
        this.appTimeZone = appTimeZone;
    }

    public ConditionEvaluator(JSONObject filterCondition, JSONObject filters) {
        this(filterCondition, filters, null);
    }

    public boolean evaluate() throws JSONException, InvalidFieldValueException, InvalidFilterException {
        if (filterCondition == null || filters == null) {
            throw new InvalidFilterException("Provided filters are null");
        }

        String filterOperator = filterCondition.optString(FilterParameter.FILTER_OPERATOR);
        Object attributeFilters = filterCondition.opt(FilterParameter.FILTERS);
        boolean isFilterSatisfied = false;

        if (!(attributeFilters instanceof JSONArray)) return false;
        JSONArray attributeFilterList = (JSONArray) attributeFilters;
        // If no filters are present, return true
        if (attributeFilterList.length() == 0) return true;

        // Special case checking whether the passed filters are all user or not
        if (isAllUserFilters(attributeFilterList)) return true;
        for (int i = 0; i < attributeFilterList.length(); i++) {
            JSONObject condition = attributeFilterList.getJSONObject(i);

            if(condition.has("filter_type") && "nested_filters".equals(condition.get("filter_type"))) {
                ConditionEvaluator evaluator = new ConditionEvaluator(condition, this.filters, this.appTimeZone);
                isFilterSatisfied = evaluator.evaluate();
                System.out.println(isFilterSatisfied);
            } else {
                AttributeFilter attributeFilter = new AttributeFilter();
                attributeFilter.serializeJson(condition);
                Object filterValue = filters.opt(attributeFilter.getName());

                boolean isDynamicValue = attributeFilter.getIsDynamicValue();
                if(isDynamicValue) {
                    Pattern pattern = Pattern.compile("\\['(.*?)'\\]");
                    Object valueList = attributeFilter.getValue();
                    if (valueList instanceof JSONArray) {
                        JSONArray value = ((JSONArray) valueList);
                        for(int j = 0;j < value.length();j++) {
                            Matcher matcher = pattern.matcher(value.getString(j));
                            if(matcher.find()) {
                                value.put(j, filters.opt(matcher.group(1)));
                            }
                        }
                    } else {
                        Matcher matcher = pattern.matcher(valueList.toString());
                        if(matcher.find()) {
                            attributeFilter.setValue(filters.opt(matcher.group(1)));
                        }
                    }
                }
                ValidateFilter validateFilter = new ValidateFilter(attributeFilter, filterValue);
                try {
                    if(validateFilter.isFiltersValid()) {
                        isFilterSatisfied = doesSatisfyFilter(attributeFilter, filterValue);
                    }
                } catch (InvalidFieldValueException e) {
                    // InvalidFieldValueException is a happy case when negate is true
                    isFilterSatisfied = attributeFilter.getNegate();
                }
            }

            if (isFilterSatisfied && filterOperator.equals(FilterOperator.OR)) {
                return true;
            }
            if (!isFilterSatisfied && filterOperator.equals(FilterOperator.AND)) {
                return false;
            }
        }
        return isFilterSatisfied;
    }

    private boolean doesSatisfyFilter(AttributeFilter attributeFilter, Object filterValue) {
        FilterConditionEvaluator filterEvaluatorObj = new FilterConditionEvaluator(attributeFilter, appTimeZone);
        return filterEvaluatorObj.evaluate(filterValue);
    }

    private boolean isAllUserFilters(JSONArray attributeFilterList) {
        if (attributeFilterList.length() > 1) return false;
        // Attribute filter will only contain one condition object when the code reach here.
        // No index out of bound exception will be thrown for this.
        JSONObject condition = attributeFilterList.getJSONObject(0);
        // If the filter type is custom segment and id of the custom segment is moe_all_users return true
        return FilterType.CUSTOM_SEGMENTS.equals(condition.optString(FilterParameter.FILTER_TYPE)) &&
                "moe_all_users".equals(condition.optString(FilterParameter.ID));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy