com.pushtechnology.diffusion.client.features.UpdateConstraint Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2023 DiffusionData Ltd., All Rights Reserved.
*
* Use is subject to license terms.
*
* NOTICE: All information contained herein is, and remains the
* property of Push Technology. The intellectual and technical
* concepts contained herein are proprietary to Push Technology and
* may be covered by U.S. and Foreign Patents, patents in process, and
* are protected by trade secret or copyright law.
*******************************************************************************/
package com.pushtechnology.diffusion.client.features;
import com.pushtechnology.diffusion.client.session.Session;
import com.pushtechnology.diffusion.client.topics.details.TopicType;
import com.pushtechnology.diffusion.datatype.json.JSON;
/**
* A constraint to be applied to an update operation or the creation of an
* update stream.
*
* Constraints describe a condition that must be satisfied for an operation to
* succeed. Constraints can be applied to the setting of a value or creation
* of an update stream. Constraints are only evaluated on the server.
*
* The constraints are evaluated using the:
*
* - active session locks
*
- existence of the topic
*
- current value of the topic
*
*
* The value of a topic can be described in several ways. The value can be
* described as an exact value, a partial value or an unset value.
*
* Constraints can be composed with one another. It is only possible to
* construct logical ANDs of constraints. Constraints can only be composed if
* the resulting constraint is satisfiable. Multiple session locks can be held
* but a topic can only have a single value. Constraints specifying multiple
* topic values cannot be constructed.
*
* Constraints can be created using a {@link UpdateConstraint.Factory}, an
* instance of which can be obtained using
* {@link com.pushtechnology.diffusion.client.Diffusion#updateConstraints
* update constraints}.
* For example:
*
*
* UpdateConstraint.Factory factory = Diffusion.updateConstraints();
* UpdateConstraint constraint = factory.locked(lock).and(factory.value(expectedValue));
*
*
*
* @author DiffusionData Limited
* @since 6.2
*/
public interface UpdateConstraint {
/**
* Returns a composed constraint that represents a logical AND of this
* constraint and another.
*
* @param other a constraint that will be logically-ANDed with this
* constraint
* @return a composed constraint that represents a logical AND of this
* constraint and the {@code other} constraint
* @throws IllegalArgumentException if the composed constraint would be
* unsatisfiable
*/
UpdateConstraint and(UpdateConstraint other);
/**
* A constraint requiring the current value of a
* {@link TopicType#JSON JSON} topic to match the partially described
* value.
*
* The code:
*
*
* Constraint.Factory factory = Diffusion.updateConstraints();
* PartialJSON constraint =
* factory.jsonValue()
* .with("/id", String.class, idValue)
* .without("/cancellation");
*
*
* creates a constraint for a JSON object with a specific ID value and no
* value for a "cancellation" property.
*
* Missing keys are matched differently to keys that are present with null
* values.
*/
interface PartialJSON extends UpdateConstraint {
/**
* Require a value at a specific position in the JSON object.
*
* The {@code pointer} is a
* JSON Pointer
* syntax reference locating the {@code value} in the JSON object.
*
* Only string, int64, and double values are supported. The null value
* may be passed for any type.
*
* @param pointer the pointer expression
* @param valueClass the value class
* @param value the value
* @param the value type of the value at the pointer
* @return a new constraint
* @throws IllegalArgumentException if the {@code pointer}
* parameter cannot be parsed as a
* JSON pointer or if the value
* class is not one of String,
* Long or Double.
*/
PartialJSON with(String pointer, Class valueClass, V value);
/**
* Require a specific position in the JSON object to be absent. This
* does not match positions that have null values.
*
* The {@code pointer} is a
* JSON Pointer
* syntax reference that should have no value in the JSON object.
*
* @param pointer the pointer expression
* @return a new constraint
* @throws IllegalArgumentException if the {@code pointer}
* parameter cannot be parsed as a
* JSON pointer
*/
PartialJSON without(String pointer);
}
/**
* Factory for the constraint types.
*
* An instance can be obtained by calling
* {@link com.pushtechnology.diffusion.client.Diffusion#updateConstraints() Diffusion.updateConstraints()}.
*/
interface Factory {
/**
* Create a constraint requiring a lock to be held by the session.
*
* This can be used to coordinate operations between multiple
* sessions.
*
* @param lock the lock
* @return the constraint
*/
UpdateConstraint locked(Session.SessionLock lock);
/**
* Create a constraint requiring the current value of a topic to match
* the supplied value.
*
* When a {@link TopicType#STRING string}, {@link TopicType#INT64 int64}
* or {@link TopicType#DOUBLE double} topic is updated to a {@code null}
* value, the topic is set to have no value. Use the {@link #noValue()}
* constraint to check if the topic has no value.
*
* This is useful when changing the value of a topic. This constraint is
* unsatisfied if no topic is present at the path, making it unsuitable
* for operations that try to add topics.
*
* @param value the value
* @param the value type
* @return the constraint
*/
UpdateConstraint value(V value);
/**
* Create a constraint requiring the topic to have no value.
*
* This is useful when setting the first value of a topic. This
* constraint is unsatisfied if no topic is present at the path, making
* it unsuitable for operations that try to add topics.
*
* @return the constraint
*/
UpdateConstraint noValue();
/**
* Create a constraint requiring the path to have no topic.
*
* This is useful when setting the first value of a topic being added
* using {@link TopicUpdate#addAndSet addAndSet} without changing the
* value if the topic already exists. This constraint is unsatisfied
* if a topic is present at the path, making it unsuitable for
* operations that try to set topics without adding them.
*
* @return the constraint
*/
UpdateConstraint noTopic();
/**
* Create a constraint that partially matches the current topic value.
*
* The topic must be a {@link TopicType#JSON JSON} topic. The
* {@link PartialJSON} partially describes the
* structure of a {@link JSON} value.
*
* @return the constraint
*/
PartialJSON jsonValue();
}
}