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

io.polyglotted.elastic.index.IndexRecord Maven / Gradle / Ivy

There is a newer version: 6.8.5
Show newest version
package io.polyglotted.elastic.index;

import io.polyglotted.common.model.MapResult;
import io.polyglotted.common.model.MapResult.ImmutableResult;
import io.polyglotted.common.model.SortedMapResult;
import io.polyglotted.elastic.common.DocStatus;
import io.polyglotted.elastic.common.MetaFields;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.elasticsearch.action.DocWriteRequest;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Objects;
import java.util.Set;

import static io.polyglotted.common.model.SortedMapResult.treeResult;
import static io.polyglotted.common.util.BaseSerializer.serializeBytes;
import static io.polyglotted.common.util.CollUtil.filterKeys;
import static io.polyglotted.common.util.NullUtil.nonNull;
import static io.polyglotted.common.util.StrUtil.notNullOrEmpty;
import static io.polyglotted.common.util.UrnUtil.safeUrnOf;
import static io.polyglotted.common.util.UrnUtil.urnOf;
import static io.polyglotted.common.util.UuidUtil.generateUuid;
import static io.polyglotted.elastic.common.MetaFields.APPROVAL_ROLES_FIELD;
import static io.polyglotted.elastic.common.MetaFields.BASE_TS_FIELD;
import static io.polyglotted.elastic.common.MetaFields.COMMENT_FIELD;
import static io.polyglotted.elastic.common.MetaFields.EXPIRY_FIELD;
import static io.polyglotted.elastic.common.MetaFields.ID_FIELD;
import static io.polyglotted.elastic.common.MetaFields.KEY_FIELD;
import static io.polyglotted.elastic.common.MetaFields.MODEL_FIELD;
import static io.polyglotted.elastic.common.MetaFields.PARENT_FIELD;
import static io.polyglotted.elastic.common.MetaFields.SCHEMA_FIELD;
import static io.polyglotted.elastic.common.MetaFields.STATUS_FIELD;
import static io.polyglotted.elastic.common.MetaFields.TIMESTAMP_FIELD;
import static io.polyglotted.elastic.common.MetaFields.TRAITFQN_FIELD;
import static io.polyglotted.elastic.common.MetaFields.TRAITID_FIELD;
import static io.polyglotted.elastic.common.MetaFields.TTL_FIELD;
import static io.polyglotted.elastic.common.MetaFields.UPDATER_FIELD;
import static io.polyglotted.elastic.common.MetaFields.USER_FIELD;
import static io.polyglotted.elastic.common.MetaFields.addMeta;
import static io.polyglotted.elastic.common.MetaFields.removeMeta;
import static io.polyglotted.elastic.index.RecordAction.CREATE;
import static io.polyglotted.elastic.index.RecordAction.DELETE;
import static io.polyglotted.elastic.index.RecordAction.UPDATE;
import static java.util.Objects.requireNonNull;

@SuppressWarnings({"unused", "WeakerAccess", "UnusedReturnValue"})
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public final class IndexRecord {
    public final String index;
    public final String model;
    public final String id;
    public final String parent;
    public final long timestamp;
    public final RecordAction action;
    public final Long baseVersion;
    public final Object source;
    private final ImmutableResult ancillary;
    public final String pipeline;

    public String keyString() { return urnOf(model, id); }

    public String simpleKey() { return safeUrnOf(model, id, timestamp); }

    public String key() { return safeUrnOf(model, parent, id, timestamp); }

    MapResult update(MapResult current) { current.putAll(ancillary); current.put(STATUS_FIELD, action.status); return current; }

    public DocWriteRequest request() { addMeta(source, KEY_FIELD, key()); return action.request(this); }

    public static Builder createRecord(String repo, String model, String id, Object source) { return createRecord(repo, model, id, null, source); }

    public static Builder createRecord(String repo, String model, String id, String parent, Object source) {
        return new Builder(CREATE, repo, model, id, parent, source);
    }

    public static Builder updateRecord(String repo, String model, String id, Long version, Object source) {
        return updateRecord(repo, model, id, null, version, source);
    }

    public static Builder updateRecord(String repo, String model, String id, String parent, Long version, Object source) {
        return expired(UPDATE, repo, model, id, parent, version, source);
    }

    public static Builder deleteRecord(String repo, String model, String id, Long version) { return deleteRecord(repo, model, id, null, version); }

    public static Builder deleteRecord(String repo, String model, String id, String parent, Long version) {
        return expired(DELETE, repo, model, id, parent, version, new LinkedHashMap<>());
    }

    public static Builder expired(RecordAction action, String repo, String model, String id, String parent, Long tstamp, Object src) {
        return new Builder(action, repo, model, id, parent, src).baseVersion(tstamp);
    }

    @Accessors(fluent = true, chain = true)
    public static class Builder {
        public final String index;
        public final String model;
        public final String id;
        public final String parent;
        private final RecordAction action;
        @Getter final String keyString;
        @Getter private final Object source;
        private final SortedMapResult ancillary = treeResult();
        private Long timestamp = null;
        private Long baseVersion = null;
        @Setter private String pipeline = null;

        private Builder(RecordAction action, String index, String modelName, String idStr, String parent, Object object) {
            this.index = requireNonNull(index);
            this.model = requireNonNull(modelName);
            byte[] bytes = getBytes(object);
            this.id = nonNull(idStr, () -> generateUuid(bytes).toString().toLowerCase());
            this.parent = parent; // can be null
            this.action = requireNonNull(action);
            this.keyString = urnOf(model, id);
            this.source = object;
            addMeta(source, MODEL_FIELD, model); addMeta(source, ID_FIELD, id);
            if (notNullOrEmpty(parent)) { addMeta(source, PARENT_FIELD, parent); }
        }

        @Override
        public boolean equals(Object o) {
            return this == o || (!(o == null || getClass() != o.getClass()) && Objects.equals(keyString, ((Builder) o).keyString));
        }

        @Override
        public int hashCode() { return Objects.hash(keyString, action); }

        public Builder timestamp(long timestampVal) {
            this.timestamp = timestampVal; addMeta(source, TIMESTAMP_FIELD, String.valueOf(timestamp));
            ancillary.put(EXPIRY_FIELD, String.valueOf(timestamp)); return this;
        }

        public Builder user(String user) {
            addMeta(source, USER_FIELD, requireNonNull(user));
            ancillary.put(UPDATER_FIELD, user); return this;
        }

        public Builder comment(String comment, boolean meta) {
            if (meta) { addMeta(source, COMMENT_FIELD, requireNonNull(comment)); }
            else { ancillary.put(COMMENT_FIELD, requireNonNull(comment)); } return this;
        }

        public Builder traitFqn(String traitFqn) { addMeta(source, TRAITFQN_FIELD, traitFqn); return this; }

        public Builder traitId(String traitId) { addMeta(source, TRAITID_FIELD, requireNonNull(traitId)); return this; }

        public Builder schema(String schema) { addMeta(source, SCHEMA_FIELD, schema); return this; }

        public Builder baseVersion(Long baseVersion) { this.baseVersion = baseVersion; return this; }

        public Builder baseTimestamp(Long baseTs) { if (baseTs != null) { addMeta(source, BASE_TS_FIELD, baseTs); } return this; }

        public Builder status(DocStatus status) { addMeta(source, STATUS_FIELD, status.name()); return this; }

        public Builder noStatus() { removeMeta(source, STATUS_FIELD); removeMeta(source, BASE_TS_FIELD); return this; }

        public Builder approvalRoles(Set roles) { if (notEmpty(roles)) { addMeta(source, APPROVAL_ROLES_FIELD, roles); } return this; }

        public Builder ttlExpiry(long ttl) { addMeta(source, TTL_FIELD, ttl); return this; }

        public IndexRecord build() {
            return new IndexRecord(index, model, id, parent, requireNonNull(timestamp), action, baseVersion, source, ancillary.immutable(), pipeline);
        }
    }

    private static byte[] getBytes(Object v) {
        return (v instanceof MapResult) ? serializeBytes(filterKeys((MapResult) v, MetaFields::isNotMeta)) : serializeBytes(v);
    }

    private static  boolean notEmpty(Collection nullable) { return nullable != null && !nullable.isEmpty(); }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy