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

io.vertx.up.unity.CompareJ Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package io.vertx.up.unity;

import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.up.eon.KName;
import io.vertx.up.eon.em.ChangeFlag;
import io.vertx.up.log.Annal;
import io.vertx.up.util.Ut;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiFunction;

/**
 * @author Lang
 */
class CompareJ {
    private static final Annal LOGGER = Annal.get(CompareJ.class);

    // ------------------------- Compare Json ------------------------
    static JsonArray ruleJReduce(final JsonArray records, final JsonArray matrix) {
        final JsonArray normalized = new JsonArray();
        Ut.itJArray(records).filter(json -> ruleJOk(json, matrix)).forEach(normalized::add);
        return normalized;
    }

    static JsonArray ruleJReduce(final JsonArray records, final Set fields) {
        final JsonArray normalized = new JsonArray();
        Ut.itJArray(records).filter(json -> ruleJOk(json, fields)).forEach(normalized::add);
        return normalized;
    }

    static boolean ruleJOk(final JsonObject record, final Set fields) {
        /*
         * All the uniqueFields must contain value
         */
        return fields.stream().allMatch(field ->
            Objects.nonNull(record.getValue(field)));
    }

    static boolean ruleJOk(final JsonObject record, final JsonArray matrix) {
        /*
         * Matrix may be multi groups
         */
        final int size = matrix.size();
        for (int idx = 0; idx < size; idx++) {
            final Object value = matrix.getValue(idx);
            final Set fields = fieldSet(value);
            if (fields.isEmpty()) {
                /*
                 * Not unique defined
                 */
                return false;
            }


            /*
             * Compare each group for matrix
             */
            final boolean match = ruleJOk(record, fields);
            if (!match) {
                return false;
            }
        }
        return true;
    }

    /*
     * Here should be some comments for group unique rules
     * 1. When you check whether the data is OK, here should be:
     *    ----> Unique 1  --> Ok
     *    ----> Unique 2  --> Ok   ----- All the rule should be Ok
     *    ----> Unique 2  --> Ok
     * 2. When you want to match whether the two record are equal, here should be:
     *    ----> Unique 1  --> Match
     *    ----> Unique 2  --> Not    ----- Any rule should be matched
     *    ----> Unique 3  --> Match
     *    Here are the priority of each Unique Rule,
     *    The situation is often
     *    1)  Primary Key
     *    2)  Unique Key
     */
    static boolean ruleJEqual(final JsonObject record, final JsonObject latest,
                              final JsonArray matrix) {
        /*
         * Matrix may be multi groups
         */
        final int size = matrix.size();
        for (int idx = 0; idx < size; idx++) {
            final Object value = matrix.getValue(idx);
            final Set fields = fieldSet(value);
            if (fields.isEmpty()) {
                /*
                 * Not unique defined, check the next
                 * rule here.
                 */
                continue;
            }
            /*
             * Compare each group for matrix
             * Find any one rule should be OK here for equal
             * 1) Primary Key    - 0
             * 2) Unique Key     - 1
             */
            final boolean equal = ruleJEqual(record, latest, fields);
            if (equal) {
                return true;
            }
        }
        return false;
    }

    static boolean ruleJEqual(final JsonObject record, final JsonObject latest,
                              final Set fields) {
        final JsonObject subR = Ut.elementSubset(record, fields);
        final JsonObject subL = Ut.elementSubset(latest, fields);
        return subR.equals(subL);
    }

    static JsonObject ruleJFind(final JsonArray source, final JsonObject expected,
                                final Set fields) {
        return Ut.itJArray(source).filter(json -> ruleJEqual(json, expected, fields))
            .findAny().orElse(new JsonObject());
    }

    static JsonObject ruleJFind(final JsonArray source, final JsonObject expected,
                                final JsonArray matrix) {
        return Ut.itJArray(source).filter(json -> ruleJEqual(json, expected, matrix))
            .findAny().orElse(new JsonObject());
    }

    private static Set fieldSet(final Object value) {
        final Set fields;
        if (value instanceof JsonArray) {
            fields = Ut.toSet((JsonArray) value);
        } else if (value instanceof String) {
            fields = new HashSet<>();
            fields.add((String) value);
        } else {
            fields = new HashSet<>();
        }
        return fields;
    }

    static ConcurrentMap compareJ(
        final JsonArray original, final JsonArray current, final Set fields) {
        return compareJ(original, current,
            (source, record) -> ruleJFind(source, record, fields));
    }

    static ConcurrentMap compareJ(
        final JsonArray original, final JsonArray current, final JsonArray matrix) {
        return compareJ(original, current,
            (source, record) -> ruleJFind(source, record, matrix));
    }

    private static ConcurrentMap compareJ(
        final JsonArray original, final JsonArray current,
        // 2 Function
        final BiFunction findFn
    ) {
        final ConcurrentMap result = new ConcurrentHashMap<>();
        result.put(ChangeFlag.UPDATE, new JsonArray());
        result.put(ChangeFlag.ADD, new JsonArray());
        result.put(ChangeFlag.DELETE, new JsonArray());
        Ut.itJArray(original).forEach(recordO -> {
            final JsonObject recordN = findFn.apply(current, recordO);
            if (Ut.isNil(recordN)) {
                // New: x, Old: o
                result.get(ChangeFlag.DELETE).add(recordO);
            } else {
                // New: o, Old: o
                // Do not overwrite `key` field because is primary key
                final JsonObject recordNC = recordN.copy();
                if (recordNC.containsKey(KName.KEY)) {
                    recordNC.remove(KName.KEY);
                }
                final JsonObject combine = recordO.copy().mergeIn(recordNC, true);
                result.get(ChangeFlag.UPDATE).add(combine);
            }
        });
        Ut.itJArray(current).forEach(recordN -> {
            final JsonObject recordO = findFn.apply(original, recordN);
            if (Ut.isNil(recordO)) {
                // New: o, Old: x
                result.get(ChangeFlag.ADD).add(recordN);
            }
        });
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy