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

io.vertx.up.uca.jooq.ActionUpsert Maven / Gradle / Ivy

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

import io.vertx.core.Future;
import io.vertx.core.json.JsonObject;
import io.vertx.up.eon.em.ChangeFlag;
import io.vertx.up.unity.Ux;
import io.vertx.up.util.Ut;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiPredicate;

/**
 * @author Lang
 */
class ActionUpsert extends AbstractAction {
    /*
     * Fetch and Update
     */
    private final transient ActionFetch fetch;
    private final transient ActionUpdate update;
    private final transient ActionInsert insert;

    ActionUpsert(final JqAnalyzer analyzer) {
        super(analyzer);
        /*
         * Operation Combine
         */
        this.fetch = new ActionFetch(analyzer);
        this.update = new ActionUpdate(analyzer);
        this.insert = new ActionInsert(analyzer);

    }

    /* Future */
     Future upsertAsync(final ID id, final T updated) {
        return this.execAsync(this.fetch.fetchByIdAsync(id), updated);
    }

     Future upsertAsync(final JsonObject criteria, final T updated) {
        return this.execAsync(this.fetch.fetchOneAsync(criteria), updated);
    }

    /* T */
     T upsert(final ID id, final T updated) {
        return this.exec(this.fetch.fetchById(id), updated);
    }

     T upsert(final JsonObject criteria, final T updated) {
        return this.exec(this.fetch.fetchOne(criteria), updated);
    }

     List upsert(final JsonObject criteria, final List updated, final BiPredicate finder) {
        /*
         * Find the original T list
         */
        final List original = this.fetch.fetch(criteria);
        /*
         * Query data by filters
         */
        final ConcurrentMap> compared = this.compared(original, updated, finder);
        /*
         * Insert & Update
         */
        final List resultList = new ArrayList<>();
        resultList.addAll(this.insert.insert(compared.get(ChangeFlag.ADD)));
        resultList.addAll(this.update.update(compared.get(ChangeFlag.UPDATE)));
        return resultList;
    }

     Future> upsertAsync(final JsonObject criteria, final List updated, final BiPredicate finder) {
        /*
         * Query data by filters ( This filters should fetch all condition list as List )
         * original
         */
        return this.fetch.fetchAsync(criteria).compose(original -> {
            /*
             * Compared original / and last list
             */
            final ConcurrentMap> compared = this.compared(original, updated, finder);
            /*
             * Insert & Update
             */
            final List>> futures = new ArrayList<>();
            futures.add(this.insert.insertAsync(compared.get(ChangeFlag.ADD)));
            futures.add(this.update.updateAsync(compared.get(ChangeFlag.UPDATE)));
            return Ux.thenCombineArrayT(futures);
        });
    }

    /*
     *  Function compare for batch processing
     */
     ConcurrentMap> compared(final List original, final List updated, final BiPredicate finder) {
        /*
         * Combine original / updated
         * list to get result for
         * INSERT / UPDATE
         */
        final List addQueue = new ArrayList<>();
        final List updateQueue = new ArrayList<>();
        /*
         * Only get `ADD` & `UPDATE`
         * Iterate original list
         * 1) If the entity is missing in original, ADD
         * 2) If the entity is existing in original, UPDATE
         */
        updated.forEach(newRecord -> {
            /*
             * New record found in `original`
             */
            final T found = Ut.elementFind(original, oldRecord -> finder.test(oldRecord, newRecord));
            if (Objects.isNull(found)) {
                addQueue.add(newRecord);
            } else {
                final T combine = this.analyzer.copyEntity(found, newRecord);
                updateQueue.add(combine);
            }
        });
        return new ConcurrentHashMap>() {
            {
                this.put(ChangeFlag.ADD, addQueue);
                this.put(ChangeFlag.UPDATE, updateQueue);
            }
        };
    }

    /*
     * Combine for `Saving` here, it could help Jooq to execute
     * Saving operation.
     *
     * Insert / Update merged
     * 1 Existing: do updating
     * 2 Missing: do missing
     */
    private  Future execAsync(final Future queried, final T updated) {
        return queried.compose(previous -> {
            if (Objects.isNull(previous)) {
                return this.insert.insertAsync(updated);
            } else {
                final T combine = this.analyzer.copyEntity(previous, updated);
                return this.update.updateAsync(combine);
            }
        });
    }

    private  T exec(final T queried, final T updated) {
        if (Objects.isNull(queried)) {
            return this.insert.insert(updated);
        } else {
            final T combine = this.analyzer.copyEntity(queried, updated);
            return this.update.update(combine);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy