package com.ejlchina.searcher;

import com.ejlchina.searcher.dialect.Dialect;
import com.ejlchina.searcher.dialect.DialectSensor;
import com.ejlchina.searcher.implement.DialectWrapper;
import com.ejlchina.searcher.operator.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 字段运算符池（支持的运算符都在这里）
 * @author Troy.Zhou @ 2022-01-19
 * @since v3.3.0
 */
public class FieldOpPool extends DialectWrapper {

    private List<FieldOp> fieldOps;

    private final Map<Object, FieldOp> cache = new ConcurrentHashMap<>();


    public FieldOpPool(List<FieldOp> fieldOps) {
        this.fieldOps = Objects.requireNonNull(fieldOps);
    }

    public FieldOpPool() {
        fieldOps = new ArrayList<>();
        fieldOps.add(new Equal());
        fieldOps.add(new NotEqual());
        fieldOps.add(new GreaterThan());
        fieldOps.add(new GreaterEqual());
        fieldOps.add(new LessThan());
        fieldOps.add(new LessEqual());
        fieldOps.add(new Between());
        fieldOps.add(new NotBetween());
        fieldOps.add(new Contain());
        fieldOps.add(new StartWith());
        fieldOps.add(new EndWith());
        fieldOps.add(new InList());
        fieldOps.add(new NotIn());
        fieldOps.add(new IsNull());
        fieldOps.add(new NotNull());
        fieldOps.add(new Empty());
        fieldOps.add(new NotEmpty());
    }


    public FieldOp getFieldOp(Object key) {
        if (key == null) {
            return null;
        }
        FieldOp fOp = cache.get(key);
        if (fOp != null) {
            return fOp;
        }
        for (FieldOp op: fieldOps) {
            if (isMatch(op, key)) {
                cache.put(key, op);
                return op;
            }
        }
        return null;
    }

    private boolean isMatch(FieldOp op, Object key) {
        if (key instanceof FieldOp) {
            return op.sameTo((FieldOp) key);
        }
        if (key instanceof String) {
            return op.isNamed((String) key);
        }
        if (key instanceof Class) {
            return op.getClass() == key;
        }
        return false;
    }

    public List<FieldOp> getFieldOps() {
        return fieldOps;
    }

    public synchronized void setFieldOps(List<FieldOp> fieldOps) {
        this.fieldOps = fieldOps;
        updateAllOpDialect();
    }

    public synchronized void addFieldOp(FieldOp fieldOp) {
        this.fieldOps.add(fieldOp);
        updateOpDialect(fieldOp);
    }

    @Override
    public synchronized void setDialect(Dialect dialect) {
        super.setDialect(dialect);
        updateAllOpDialect();
    }

    private void updateAllOpDialect() {
        for (FieldOp op : fieldOps) {
            updateOpDialect(op);
        }
    }

    private void updateOpDialect(FieldOp op) {
        if (op instanceof DialectSensor) {
            ((DialectSensor) op).setDialect(getDialect());
        }
    }

}


@@ -1579,24 +1579,140 @@
 e.get(key);%0A
+        if (fOp == null && key instanceof FieldOp) %7B%0A            fOp = cache.get(((FieldOp) key).name());%0A        %7D%0A
         if (
@@ -1829,24 +1829,213 @@
 op, key)) %7B%0A
+                if (key instanceof FieldOp) %7B%0A                    // %E9%98%B2%E6%AD%A2%E7%94%A8%E6%88%B7%E5%AF%B9%E5%90%8C%E4%B8%80%E4%B8%AA%E8%BF%90%E7%AE%97%E7%AC%A6 new %E4%BA%86%E5%BE%88%E5%A4%9A%E6%AC%A1%E5%AF%BC%E8%87%B4 cache %E8%86%A8%E8%83%80%0A                    cache.put(((FieldOp) key).name(), op);%0A                %7D else %7B%0A    
             
@@ -2054,24 +2054,42 @@
 t(key, op);%0A
+                %7D%0A
             
@@ -3298,9 +3298,8 @@
    %7D%0A%0A%7D%0A
-%0A

修复：当用户对同一个运算符 new 了很多次时会导致 FieldOpPool 膨胀问题