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

io.debezium.document.Document Maven / Gradle / Ivy

/*
 * Copyright Debezium Authors.
 *
 * Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
 */
package io.debezium.document;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import io.debezium.annotation.NotThreadSafe;

/**
 * A document contains multiple {@link Field}s, each with a name and possibly-null {@link Value}. A single document can only
 * contain a single field with a given name.
 *
 * @author Randall Hauch
 */
@NotThreadSafe
public interface Document extends Iterable, Comparable {

    static interface Field extends Comparable {

        /**
         * Get the name of the field
         *
         * @return the field's name; never null
         */
        CharSequence getName();

        /**
         * Get the value of the field.
         *
         * @return the field's value; may be null
         */
        Value getValue();

        default boolean isNull() {
            Value v = getValue();
            return v == null || v.isNull();
        }

        default boolean isNotNull() {
            return !isNull();
        }

        @Override
        default int compareTo(Field that) {
            if (that == null) {
                return 1;
            }
            int diff = this.getName().toString().compareTo(that.getName().toString());
            if (diff != 0) {
                return diff;
            }
            return this.getValue().compareTo(that.getValue());
        }
    }

    static Field field(String name, Value value) {
        return new BasicField(name, value);
    }

    static Field field(String name, Object value) {
        return new BasicField(name, Value.create(value));
    }

    static Document create() {
        return new BasicDocument();
    }

    static Document create(CharSequence fieldName, Object value) {
        return new BasicDocument().set(fieldName, value);
    }

    static Document create(CharSequence fieldName1, Object value1, CharSequence fieldName2, Object value2) {
        return new BasicDocument().set(fieldName1, value1).set(fieldName2, value2);
    }

    static Document create(CharSequence fieldName1, Object value1, CharSequence fieldName2, Object value2, CharSequence fieldName3,
                           Object value3) {
        return new BasicDocument().set(fieldName1, value1).set(fieldName2, value2).set(fieldName3, value3);
    }

    static Document create(CharSequence fieldName1, Object value1, CharSequence fieldName2, Object value2, CharSequence fieldName3,
                           Object value3, CharSequence fieldName4, Object value4) {
        return new BasicDocument().set(fieldName1, value1).set(fieldName2, value2).set(fieldName3, value3).set(fieldName4, value4);
    }

    static Document create(CharSequence fieldName1, Object value1, CharSequence fieldName2, Object value2, CharSequence fieldName3,
                           Object value3, CharSequence fieldName4, Object value4, CharSequence fieldName5, Object value5) {
        return new BasicDocument().set(fieldName1, value1).set(fieldName2, value2).set(fieldName3, value3).set(fieldName4, value4)
                .set(fieldName5, value5);
    }

    static Document create(CharSequence fieldName1, Object value1, CharSequence fieldName2, Object value2, CharSequence fieldName3,
                           Object value3, CharSequence fieldName4, Object value4, CharSequence fieldName5, Object value5,
                           CharSequence fieldName6, Object value6) {
        return new BasicDocument().set(fieldName1, value1).set(fieldName2, value2).set(fieldName3, value3).set(fieldName4, value4)
                .set(fieldName5, value5).set(fieldName6, value6);
    }

    /**
     * Return the number of name-value fields in this object.
     *
     * @return the number of name-value fields; never negative
     */
    int size();

    /**
     * Return whether this document contains no fields and is therefore empty.
     *
     * @return true if there are no fields in this document, or false if there is at least one.
     */
    boolean isEmpty();

    /**
     * Remove all fields from this document.
     */
    void clear();

    /**
     * Determine if this contains a field with the given name.
     *
     * @param fieldName The name of the field
     * @return true if the field exists, or false otherwise
     */
    boolean has(CharSequence fieldName);

    /**
     * Checks if this object contains all of the fields in the supplied document.
     *
     * @param document The document with the fields that should be in this document
     * @return true if this document contains all of the fields in the supplied document, or false otherwise
     */
    boolean hasAll(Document document);

    /**
     * Set the value at the given path resolved against this document, optionally adding any missing intermediary documents
     * or arrays based upon the format of the path segments.
     *
     * @param path the path at which the value is to be set
     * @param addIntermediaries true if any missing intermediary fields should be created, or false if any missing
     *            intermediary fields should be handled as an error via {@code invalid}
     * @param value the value that should be set at the given path; may be null or a {@link Value#nullValue() null value}
     * @param invalid the function that should be called if the supplied path cannot be resolved; may not be null
     * @return the {@code value} if successful or the {@link Optional#empty() empty (not present)} optional value if
     *         the path was invalid and could not be resolved (and {@code invalid} is invoked)
     */
    default Optional set(Path path, boolean addIntermediaries, Value value, Consumer invalid) {
        if (path == null) {
            return Optional.empty();
        }
        if (path.isRoot()) {
            // This is an invalid path, since we don't know what to do with the value given just a root path ...
            invalid.accept(path);
            return Optional.empty();
        }
        if (path.isSingle()) {
            // Perform a simple set ...
            set(path.lastSegment().get(), value);
            return Optional.ofNullable(value);
        }
        // Otherwise, we need to find the parent that will contain the value ...
        Path parentPath = path.parent().get();
        Optional parent = Optional.empty();
        if (!addIntermediaries) {
            // Any missing intermediaries is considered invalid ...
            parent = find(parentPath, (missingPath, missingIndex) -> {
                invalid.accept(missingPath); // invoke the invalid handler
                return Optional.empty();
            }, invalid);
        }
        else {
            // Create any missing intermediaries using the segment after the missing segment to determine which
            // type of intermediate value to add ...
            parent = find(parentPath, (missingPath, missingIndex) -> {
                String nextSegment = path.segment(missingIndex + 1); // can always find next segment 'path' (not 'parentPath')...
                if (Path.Segments.isArrayIndex(nextSegment)) {
                    return Optional.of(Value.create(Array.create()));
                }
                else {
                    return Optional.of(Value.create(Document.create()));
                }
            }, invalid);
        }
        if (!parent.isPresent()) {
            return Optional.empty();
        }
        String lastSegment = path.lastSegment().get();
        Value parentValue = parent.get();
        if (parentValue.isDocument()) {
            parentValue.asDocument().set(lastSegment, value);
        }
        else if (parentValue.isArray()) {
            Array array = parentValue.asArray();
            if (Path.Segments.isAfterLastIndex(lastSegment)) {
                array.add(value);
            }
            else {
                int index = Path.Segments.asInteger(lastSegment).get();
                array.setValue(index, value);
            }
        }
        else {
            // The parent is not a document or array ...
            invalid.accept(path);
            return Optional.empty();
        }
        return Optional.of(value);
    }

    /**
     * Attempt to find the value at the given path.
     *
     * @param path the path to find
     * @return the optional value at this path, which is {@link Optional#isPresent() present} if the value was found at that
     *         path or is {@link Optional#empty() empty (not present)} if there is no value at the path or if the path was not
     *         valid
     */
    default Optional find(Path path) {
        return find(path, (missingPath, missingIndex) -> Optional.empty(), (invalidPath) -> {
        });
    }

    /**
     * Attempt to find the value at the given path, optionally creating missing segments.
     *
     * @param path the path to find
     * @param missingSegment function called when a segment in the path does not exist, and which should return a new value
     *            if one should be created or {@link Optional#empty()} if nothing should be created and {@code invalid} function
     *            should be called by this method
     * @param invalid function called when the supplied path is invalid; in this case, this method also returns
     *            {@link Optional#empty()}
     * @return the optional value at this path, which is {@link Optional#isPresent() present} if the value was found at that
     *         path or is {@link Optional#empty() empty (not present)} if there is no value at the path or if the path was not
     *         valid
     */
    default Optional find(Path path, BiFunction> missingSegment, Consumer invalid) {
        if (path == null) {
            return Optional.empty();
        }
        if (path.isRoot()) {
            return Optional.of(Value.create(this));
        }
        Value value = Value.create(this);
        int i = 0;
        for (String segment : path) {
            if (value.isDocument()) {
                Value existingValue = value.asDocument().get(segment);
                if (Value.isNull(existingValue)) {
                    // It does not exist ...
                    Optional newValue = missingSegment.apply(path, i);
                    if (newValue.isPresent()) {
                        // Add the new value (whatever it is) ...
                        Document doc = value.asDocument();
                        doc.set(segment, newValue.get());
                        value = doc.get(segment);
                    }
                    else {
                        return Optional.empty();
                    }
                }
                else {
                    value = existingValue;
                }
            }
            else if (value.isArray()) {
                Array array = value.asArray();
                if (Path.Segments.isAfterLastIndex(segment)) {
                    // This means "after the last index", so call it as missing ...
                    Optional newValue = missingSegment.apply(path, i);
                    if (newValue.isPresent()) {
                        // Add the new value (whatever it is) ...
                        value = newValue.get();
                        array.add(value);
                    }
                    else {
                        return Optional.empty();
                    }
                }
                else {
                    Optional index = Path.Segments.asInteger(segment);
                    if (index.isPresent()) {
                        // This is an index ...
                        if (array.has(index.get())) {
                            value = array.get(index.get());
                        }
                        else if (array.size() == index.get()) {
                            // We can add at this index ...
                            Optional newValue = missingSegment.apply(path, i);
                            if (newValue.isPresent()) {
                                // Add the new value (whatever it is) ...
                                array.add(newValue.get());
                            }
                            else {
                                return Optional.empty();
                            }
                        }
                        else {
                            // The index is not valid (it's too big to be an existing or the next index) ...
                            invalid.accept(path.subpath(i));
                            return Optional.empty();
                        }
                    }
                    else {
                        // This is not an array index but we're expecting it to be, so this is a bad path
                        invalid.accept(path.subpath(i));
                        return Optional.empty();
                    }
                }
            }
            else {
                // We're supposed to find the segment within this value, but it's not a document or array ...
                invalid.accept(path.subpath(i));
                return Optional.empty();
            }
            ++i;
        }
        return Optional.of(value);
    }

    /**
     * Find a document at the given path and obtain a stream over its fields. This will return an empty stream when:
     * 
    *
  • a value does not exist in this document at the supplied path; or
  • *
  • a non-document value does exist in this document at the supplied path; or
  • *
  • a document value does exist in this document at the supplied path, but that document is empty
  • *
* * @param path the path to the contained document * @return the stream of fields in the document at the given path; never null */ default Stream children(Path path) { Value parent = find(path).orElse(Value.create(Document.create())); if (!parent.isDocument()) { return Stream.empty(); } return parent.asDocument().stream(); } /** * Find the document at the given field name and obtain a stream over its fields. This will return an empty stream when: *
    *
  • a field with the given name does not exist in this document; or
  • *
  • a field with the given name does exist in this document but the value is not a document; or
  • *
  • a field with the given name does exist in this document and the value is an empty document
  • *
* * @param fieldName the path to the contained document * @return the stream of fields within the nested document; never null */ default Stream children(String fieldName) { Document doc = getDocument(fieldName); if (doc == null) { return Stream.empty(); } return doc.stream(); } /** * Gets the field in this document with the given field name. * * @param fieldName The name of the field * @return The field, if found, or null otherwise */ default Field getField(CharSequence fieldName) { Value value = get(fieldName); return value != null ? new BasicField(fieldName, value) : null; } /** * Gets the value in this document for the given field name. * * @param fieldName The name of the field * @return The field value, if found, or null otherwise */ default Value get(CharSequence fieldName) { return get(fieldName, null); } /** * Gets the value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field * @return The field value, if found, or , or defaultValue if there is no such field */ Value get(CharSequence fieldName, Comparable defaultValue); /** * Get the boolean value in this document for the given field name. * * @param fieldName The name of the field * @return The boolean field value, if found, or null if there is no such field or if the value is not a boolean */ default Boolean getBoolean(CharSequence fieldName) { Value value = get(fieldName); return value != null && value.isBoolean() ? value.asBoolean() : null; } /** * Get the boolean value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a boolean * @return The boolean field value if found, or defaultValue if there is no such field or if the value is not a * boolean */ default boolean getBoolean(CharSequence fieldName, boolean defaultValue) { Value value = get(fieldName); return value != null && value.isBoolean() ? value.asBoolean().booleanValue() : defaultValue; } /** * Get the integer value in this document for the given field name. * * @param fieldName The name of the field * @return The integer field value, if found, or null if there is no such field or if the value is not an integer */ default Integer getInteger(CharSequence fieldName) { Value value = get(fieldName); return value != null && value.isInteger() ? value.asInteger() : null; } /** * Get the integer value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a integer * @return The integer field value if found, or defaultValue if there is no such field or if the value is not a * integer */ default int getInteger(CharSequence fieldName, int defaultValue) { Value value = get(fieldName); return value != null && value.isInteger() ? value.asInteger().intValue() : defaultValue; } /** * Get the integer value in this document for the given field name. * * @param fieldName The name of the field * @return The long field value, if found, or null if there is no such field or if the value is not a long value */ default Long getLong(CharSequence fieldName) { Value value = get(fieldName); return value != null && value.isLong() ? value.asLong() : null; } /** * Get the long value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a long value * @return The long field value if found, or defaultValue if there is no such field or if the value is not a long * value */ default long getLong(CharSequence fieldName, long defaultValue) { Value value = get(fieldName); return value != null && value.isLong() ? value.asLong().longValue() : defaultValue; } /** * Get the double value in this document for the given field name. * * @param fieldName The name of the field * @return The double field value, if found, or null if there is no such field or if the value is not a double */ default Double getDouble(CharSequence fieldName) { Value value = get(fieldName); return value != null && value.isDouble() ? value.asDouble() : null; } /** * Get the double value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a double * @return The double field value if found, or defaultValue if there is no such field or if the value is not a * double */ default double getDouble(CharSequence fieldName, double defaultValue) { Value value = get(fieldName); return value != null && value.isDouble() ? value.asDouble().doubleValue() : defaultValue; } /** * Get the double value in this document for the given field name. * * @param fieldName The name of the field * @return The double field value, if found, or null if there is no such field or if the value is not a double */ default Float getFloat(CharSequence fieldName) { Value value = get(fieldName); return value != null && value.isFloat() ? value.asFloat() : null; } /** * Get the float value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a double * @return The double field value if found, or defaultValue if there is no such field or if the value is not a * double */ default float getFloat(CharSequence fieldName, float defaultValue) { Value value = get(fieldName); return value != null && value.isFloat() ? value.asFloat().floatValue() : defaultValue; } /** * Get the number value in this document for the given field name. * * @param fieldName The name of the field * @return The number field value, if found, or null if there is no such field or if the value is not a number */ default Number getNumber(CharSequence fieldName) { return getNumber(fieldName, null); } /** * Get the number value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a number * @return The number field value if found, or defaultValue if there is no such field or if the value is not a * number */ default Number getNumber(CharSequence fieldName, Number defaultValue) { Value value = get(fieldName); return value != null && value.isNumber() ? value.asNumber() : defaultValue; } /** * Get the big integer value in this document for the given field name. * * @param fieldName The name of the field * @return The big integer field value, if found, or null if there is no such field or if the value is not a big integer */ default BigInteger getBigInteger(CharSequence fieldName) { return getBigInteger(fieldName, null); } /** * Get the big integer value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a big integer * @return The big integer field value, if found, or null if there is no such field or if the value is not a big integer */ default BigInteger getBigInteger(CharSequence fieldName, BigInteger defaultValue) { Value value = get(fieldName); return value != null && value.isBigInteger() ? value.asBigInteger() : defaultValue; } /** * Get the big decimal value in this document for the given field name. * * @param fieldName The name of the field * @return The big decimal field value, if found, or null if there is no such field or if the value is not a big decimal */ default BigDecimal getBigDecimal(CharSequence fieldName) { return getBigDecimal(fieldName, null); } /** * Get the big decimal value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a big decimal * @return The big decimal field value, if found, or null if there is no such field or if the value is not a big decimal */ default BigDecimal getBigDecimal(CharSequence fieldName, BigDecimal defaultValue) { Value value = get(fieldName); return value != null && value.isBigDecimal() ? value.asBigDecimal() : defaultValue; } /** * Get the string value in this document for the given field name. * * @param fieldName The name of the field * @return The string field value, if found, or null if there is no such field or if the value is not a string */ default String getString(CharSequence fieldName) { return getString(fieldName, null); } /** * Get the string value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default value to return if there is no such field or if the value is not a string * @return The string field value if found, or defaultValue if there is no such field or if the value is not a * string */ default String getString(CharSequence fieldName, String defaultValue) { Value value = get(fieldName); return value != null && value.isString() ? value.asString() : defaultValue; } /** * Get the Base64 encoded binary value in this document for the given field name. * * @param fieldName The name of the field * @return The binary field value, if found, or null if there is no such field or if the value is not a binary value */ default byte[] getBytes(CharSequence fieldName) { Value value = get(fieldName); return value != null && value.isBinary() ? value.asBytes() : null; } /** * Get the array value in this document for the given field name. * * @param fieldName The name of the field * @return The array field value (as a list), if found, or null if there is no such field or if the value is not an array */ default Array getArray(CharSequence fieldName) { return getArray(fieldName, null); } /** * Get the array value in this document for the given field name. * * @param fieldName The name of the field * @param defaultValue the default array that should be returned if there is no such field * @return The array field value (as a list), if found, or the default value if there is no such field or if the value is not * an array */ default Array getArray(CharSequence fieldName, Array defaultValue) { Value value = get(fieldName); return value != null && value.isArray() ? value.asArray() : defaultValue; } /** * Get the existing array value in this document for the given field name, or create a new array if there is no existing array * at this field. * * @param fieldName The name of the field * @return The editable array field value; never null */ default Array getOrCreateArray(CharSequence fieldName) { Value value = get(fieldName); if (value == null || value.isNull()) { return setArray(fieldName, (Array) null); } return value.asArray(); } /** * Get the document value in this document for the given field name. * * @param fieldName The name of the field * @return The document field value, if found, or null if there is no such field or if the value is not a document */ default Document getDocument(CharSequence fieldName) { Value value = get(fieldName); return value != null && value.isDocument() ? value.asDocument() : null; } /** * Get the existing document value in this document for the given field name, or create a new document if there is no existing * document at this field. * * @param fieldName The name of the field * @return The editable document field value; null if the field exists but is not a document */ default Document getOrCreateDocument(CharSequence fieldName) { Value value = get(fieldName); if (value == null || value.isNull()) { return setDocument(fieldName, (Document) null); } return value.asDocument(); } /** * Determine whether this object has a field with the given the name and the value is null. This is equivalent to calling: * *
     * this.get(name) instanceof Null;
     * 
* * @param fieldName The name of the field * @return true if the field exists but is null, or false otherwise * @see #isNullOrMissing(CharSequence) */ default boolean isNull(CharSequence fieldName) { Value value = get(fieldName); return value != null && value.isNull(); } /** * Determine whether this object has a field with the given the name and the value is null, or if this object has no field * with * the given name. This is equivalent to calling: * *
     * Null.matches(this.get(name));
     * 
* * @param fieldName The name of the field * @return true if the field value for the name is null or if there is no such field. * @see #isNull(CharSequence) */ default boolean isNullOrMissing(CharSequence fieldName) { Value value = get(fieldName); return value == null || value.isNull(); } /** * Returns this object's fields' names * * @return The names of the fields in this object */ Iterable keySet(); /** * Obtain a clone of this document. * * @return the clone of this document; never null */ Document clone(); /** * Remove the field with the supplied name, and return the value. * * @param name The name of the field * @return the value that was removed, or null if there was no such value */ Value remove(CharSequence name); /** * If the supplied name is provided, then remove the field with the supplied name and return the value. * * @param name The optional name of the field * @return the value that was removed, or null if the field was not present or there was no such value */ default Value remove(Optional name) { return name.isPresent() ? remove(name.get()) : null; } /** * Remove all fields from this document. * * @return This document, to allow for chaining methods */ Document removeAll(); /** * Sets on this object all name/value pairs from the supplied object. If the supplied object is null, this method does * nothing. * * @param fields the name/value pairs to be set on this object; may not be null * @return This document, to allow for chaining methods */ default Document putAll(Iterator fields) { while (fields.hasNext()) { Field field = fields.next(); setValue(field.getName(), field.getValue()); } return this; } /** * Sets on this object all name/value pairs from the supplied object. If the supplied object is null, this method does * nothing. * * @param fields the name/value pairs to be set on this object; may not be null * @return This document, to allow for chaining methods */ default Document putAll(Iterable fields) { for (Field field : fields) { setValue(field.getName(), field.getValue()); } return this; } /** * Attempts to copy all of the acceptable fields from the source and set on this document, overwriting any existing * values. * * @param fields the name/value pairs to be set on this object; may not be null * @param acceptableFieldNames the predicate to determine which fields from the source should be copied; may not be null * @return This document, to allow for chaining methods */ default Document putAll(Iterable fields, Predicate acceptableFieldNames) { for (Field field : fields) { if (acceptableFieldNames.test(field.getName())) { setValue(field.getName(), field.getValue()); } } return this; } /** * Sets on this object all key/value pairs from the supplied map. If the supplied map is null, this method does nothing. * * @param fields the map containing the name/value pairs to be set on this object * @return This document, to allow for chaining methods */ default Document putAll(Map fields) { if (fields != null) { for (Map.Entry entry : fields.entrySet()) { set(entry.getKey(), entry.getValue()); } } return this; } /** * Returns a sequential {@code Stream} with this array as its source. * * @return a sequential {@code Stream} over the elements in this collection */ default Stream stream() { return StreamSupport.stream(spliterator(), false); } default void forEach(BiConsumer consumer) { Path root = Path.root(); stream().forEach((field) -> { Path path = root.append(field.getName().toString()); Value value = field.getValue(); if (value.isDocument()) { value.asDocument().forEach((p, v) -> { consumer.accept(path.append(p), v); }); } else if (value.isArray()) { value.asArray().forEach((entry) -> { consumer.accept(path.append(Integer.toString(entry.getIndex())), entry.getValue()); }); } else { consumer.accept(path, value); } }); } /** * Transform all of the field values using the supplied {@link BiFunction transformer function}. * * @param transformer the transformer that should be used to transform each field value; may not be null * @return this document with transformed fields, or this document if the transformer changed none of the values */ default Document transform(BiFunction transformer) { for (Field field : this) { Value existing = get(field.getName()); Value updated = transformer.apply(field.getName(), existing); if (updated == null) { updated = Value.nullValue(); } if (updated != existing) { setValue(field.getName(), updated); } } return this; } /** * Set the value for the field with the given name to be a binary value. The value will be encoded as Base64. * * @param name The name of the field * @param value the new value * @return This document, to allow for chaining methods */ default Document set(CharSequence name, Object value) { if (value instanceof Value) { setValue(name, (Value) value); return this; } Value wrapped = Value.create(value); setValue(name, wrapped); return this; } /** * Set the value for the field with the given name to be a null value. The {@link #isNull(CharSequence)} methods can be used * to * determine if a field has been set to null, or {@link #isNullOrMissing(CharSequence)} if the field has not be set or if it * has * been set to null. * * @param name The name of the field * @return This document, to allow for chaining methods * @see #isNull(CharSequence) * @see #isNullOrMissing(CharSequence) */ default Document setNull(CharSequence name) { setValue(name, Value.nullValue()); return this; } /** * Set the value for the field with the given name to the supplied boolean value. * * @param name The name of the field * @param value the new value for the field * @return This document, to allow for chaining methods */ default Document setBoolean(CharSequence name, boolean value) { setValue(name, Value.create(value)); return this; } /** * Set the value for the field with the given name to the supplied integer value. * * @param name The name of the field * @param value the new value for the field * @return This document, to allow for chaining methods */ default Document setNumber(CharSequence name, int value) { setValue(name, Value.create(value)); return this; } /** * Set the value for the field with the given name to the supplied long value. * * @param name The name of the field * @param value the new value for the field * @return This document, to allow for chaining methods */ default Document setNumber(CharSequence name, long value) { setValue(name, Value.create(value)); return this; } /** * Set the value for the field with the given name to the supplied float value. * * @param name The name of the field * @param value the new value for the field * @return This document, to allow for chaining methods */ default Document setNumber(CharSequence name, float value) { setValue(name, Value.create(value)); return this; } /** * Set the value for the field with the given name to the supplied double value. * * @param name The name of the field * @param value the new value for the field * @return This document, to allow for chaining methods */ default Document setNumber(CharSequence name, double value) { setValue(name, Value.create(value)); return this; } /** * Set the value for the field with the given name to the supplied big integer value. * * @param name The name of the field * @param value the new value for the field * @return This document, to allow for chaining methods */ default Document setNumber(CharSequence name, BigInteger value) { setValue(name, Value.create(value)); return this; } /** * Set the value for the field with the given name to the supplied big integer value. * * @param name The name of the field * @param value the new value for the field * @return This document, to allow for chaining methods */ default Document setNumber(CharSequence name, BigDecimal value) { setValue(name, Value.create(value)); return this; } /** * Set the value for the field with the given name to the supplied string value. * * @param name The name of the field * @param value the new value for the field * @return This document, to allow for chaining methods */ default Document setString(CharSequence name, String value) { setValue(name, Value.create(value)); return this; } /** * Increment the numeric value in the given field by the designated amount. * * @param name The name of the field * @param increment the amount to increment the existing value; may be negative to decrement * @return this array to allow for chaining methods * @throws IllegalArgumentException if the current value is not a number */ default Document increment(CharSequence name, int increment) { return increment(name, Value.create(increment)); } /** * Increment the numeric value in the given field by the designated amount. * * @param name The name of the field * @param increment the amount to increment the existing value; may be negative to decrement * @return this array to allow for chaining methods * @throws IllegalArgumentException if the current value is not a number */ default Document increment(CharSequence name, long increment) { return increment(name, Value.create(increment)); } /** * Increment the numeric value in the given field by the designated amount. * * @param name The name of the field * @param increment the amount to increment the existing value; may be negative to decrement * @return this array to allow for chaining methods * @throws IllegalArgumentException if the current value is not a number */ default Document increment(CharSequence name, double increment) { return increment(name, Value.create(increment)); } /** * Increment the numeric value in the given field by the designated amount. * * @param name The name of the field * @param increment the amount to increment the existing value; may be negative to decrement * @return this array to allow for chaining methods * @throws IllegalArgumentException if the current value is not a number */ default Document increment(CharSequence name, float increment) { return increment(name, Value.create(increment)); } /** * Increment the numeric value in the given field by the designated amount. * * @param name The name of the field * @param increment the amount to increment the existing value; may be negative to decrement * @return this array to allow for chaining methods * @throws IllegalArgumentException if the current value is not a number */ Document increment(CharSequence name, Value increment); /** * Set the value for the field with the given name to be a binary value. The value will be encoded as Base64. * * @param name The name of the field * @param data the bytes for the binary value * @return This document, to allow for chaining methods */ default Document setBinary(CharSequence name, byte[] data) { setValue(name, Value.create(data)); return this; } /** * Set the value for the field with the given name. * * @param name The name of the field * @param value the new value * @return This document, to allow for chaining methods */ Document setValue(CharSequence name, Value value); /** * Set the field on this document. * * @param field The field * @return This document, to allow for chaining methods */ default Document setValue(Field field) { return setValue(field.getName(), field.getValue()); } /** * Set the value for the field with the given name to be a new, empty Document. * * @param name The name of the field * @return The editable document that was just created; never null */ default Document setDocument(CharSequence name) { return setDocument(name, Document.create()); } /** * Set the value for the field with the given name to be the supplied Document. * * @param name The name of the field * @param document the document; if null, a new document will be created * @return The document that was just set as the value for the named field; never null and may or may not be the same * instance as the supplied document. */ default Document setDocument(CharSequence name, Document document) { if (document == null) { document = Document.create(); } setValue(name, Value.create(document)); return getDocument(name); } /** * Set the value for the field with the given name to be a new, empty array. * * @param name The name of the field * @return The array that was just created; never null */ default Array setArray(CharSequence name) { return setArray(name, Array.create()); } /** * Set the value for the field with the given name to be the supplied array. * * @param name The name of the field * @param array the array * @return The array that was just set as the value for the named field; never null and may or may not be the same * instance as the supplied array. */ default Array setArray(CharSequence name, Array array) { if (array == null) { array = Array.create(); } setValue(name, Value.create(array)); return getArray(name); } /** * Set the value for the field with the given name to be the supplied array. * * @param name The name of the field * @param values the (valid) values for the array * @return The array that was just set as the value for the named field; never null and may or may not be the same * instance as the supplied array. */ default Array setArray(CharSequence name, Object... values) { return setArray(name, Array.create(values)); } /** * Compare this Document to the specified Document, taking into account the order of the fields. * * @param that the other Document to be compared to this object * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ @Override int compareTo(Document that); /** * Compare this Document to the specified Document, without regard to the order of the fields. * * @param that the other Document to be compared to this object * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ int compareToWithoutFieldOrder(Document that); /** * Compare this Document to the specified Document, without regard to the order of the fields and only using the fields * that are in both documents. * * @param that the other Document to be compared to this object * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ int compareToUsingSimilarFields(Document that); /** * Compare this Document to the specified Document, optionally comparing the fields in the same order. * * @param that the other Document to be compared to this object * @param enforceFieldOrder {@code true} if the documents should be compared using their existing field order, or * {@code false} if the field order should not affect the result. * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ int compareTo(Document that, boolean enforceFieldOrder); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy