org.eclipse.ditto.things.api.ThingSnapshotTaken Maven / Gradle / Ivy
/*
* Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.ditto.things.api;
import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import org.eclipse.ditto.json.JsonFactory;
import org.eclipse.ditto.json.JsonField;
import org.eclipse.ditto.json.JsonFieldDefinition;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.base.model.common.ConditionChecker;
import org.eclipse.ditto.base.model.entity.metadata.Metadata;
import org.eclipse.ditto.base.model.headers.DittoHeaders;
import org.eclipse.ditto.base.model.json.FieldType;
import org.eclipse.ditto.base.model.json.JsonParsableEvent;
import org.eclipse.ditto.base.model.json.JsonSchemaVersion;
import org.eclipse.ditto.policies.model.PolicyId;
import org.eclipse.ditto.policies.model.PolicyIdInvalidException;
import org.eclipse.ditto.things.model.ThingId;
import org.eclipse.ditto.things.model.ThingIdInvalidException;
import org.eclipse.ditto.base.api.persistence.PersistenceLifecycle;
import org.eclipse.ditto.base.api.persistence.SnapshotTaken;
/**
* Event published when a thing snapshot is taken.
*/
@JsonParsableEvent(name = ThingSnapshotTaken.NAME, typePrefix = ThingSnapshotTaken.TYPE_PREFIX)
public final class ThingSnapshotTaken extends SnapshotTaken {
/**
* Pub-sub topic of this event.
*/
public static final String PUB_SUB_TOPIC = "thing:snapshottaken";
/**
* The resource type of this event.
*/
static final String RESOURCE_TYPE = "thing";
/**
* The prefix of this event's type.
*/
static final String TYPE_PREFIX = RESOURCE_TYPE + ":";
static final String NAME = "thingSnapshotTaken";
/**
* The type of this event.
*/
static final String TYPE = TYPE_PREFIX + NAME;
static final JsonFieldDefinition JSON_POLICY_ID =
JsonFieldDefinition.ofString("policyId", FieldType.REGULAR, JsonSchemaVersion.V_2);
private final ThingId thingId;
@Nullable private final PolicyId policyId;
private ThingSnapshotTaken(final Builder builder) {
super(TYPE,
builder.revisionNumber,
builder.timestamp,
builder.metadata,
builder.thingJson,
builder.lifecycle,
builder.dittoHeaders);
thingId = builder.thingId;
policyId = builder.policyId;
}
/**
* Returns a new builder with a fluent API for creating a {@code ThingSnapshotTaken}.
*
* @param thingId the ID of the thing of which a snapshot was taken.
* @param revisionNumber the revision number of the thing of which a snapshot was taken.
* @param lifecycle the lifecycle of the thing of which a snapshot was taken.
* @param thingJson the JSON representation of the thing of which a snapshot was taken.
* @return the builder.
* @throws NullPointerException if any argument is {@code null}.
*/
public static Builder newBuilder(final ThingId thingId,
final long revisionNumber,
final PersistenceLifecycle lifecycle,
final JsonObject thingJson) {
return new Builder(ConditionChecker.checkNotNull(thingId, "thingId"),
revisionNumber,
ConditionChecker.checkNotNull(lifecycle, "lifecycle"),
ConditionChecker.checkNotNull(thingJson, "thingJson"));
}
/**
* Deserializes a {@code ThingSnapshotTaken} instance from the specified JSON object.
*
* @param jsonObject the JSON object that should be deserialized.
* @param dittoHeaders the headers of the deserialized event.
* @return the deserialized ThingSnapshotTaken instance.
* @throws NullPointerException if any argument is {@code null}.
* @throws org.eclipse.ditto.json.JsonMissingFieldException – if {@code jsonObject} did not contain all required
* fields.
* @throws org.eclipse.ditto.json.JsonParseException if {@code jsonObject} does not represent a valid
* {@code ThingSnapshotTaken}.
*/
public static ThingSnapshotTaken fromJson(final JsonObject jsonObject, final DittoHeaders dittoHeaders) {
ConditionChecker.checkNotNull(jsonObject, "jsonObject");
ConditionChecker.checkNotNull(dittoHeaders, "dittoHeaders");
final var deserializer = JsonDeserializer.of(jsonObject, TYPE);
return newBuilder(deserializeThingId(jsonObject),
deserializer.deserializeRevision(),
deserializer.deserializePersistenceLifecycle(),
deserializer.deserializeEntity())
.policyId(deserializePolicyId(jsonObject))
.timestamp(deserializer.deserializeTimestamp())
.metadata(deserializer.deserializeMetadata())
.dittoHeaders(dittoHeaders)
.build();
}
private static ThingId deserializeThingId(final JsonObject jsonObject) {
final var fieldDefinition = SnapshotTaken.JsonFields.ENTITY_ID;
try {
return ThingId.of(jsonObject.getValueOrThrow(fieldDefinition));
} catch (final ThingIdInvalidException e) {
throw JsonDeserializer.getJsonParseException(fieldDefinition, ThingId.class, e);
}
}
@Nullable
private static PolicyId deserializePolicyId(final JsonObject jsonObject) {
try {
return jsonObject.getValue(JSON_POLICY_ID)
.map(PolicyId::of)
.orElse(null);
} catch (final PolicyIdInvalidException e) {
throw JsonDeserializer.getJsonParseException(JSON_POLICY_ID, PolicyId.class, e);
}
}
/**
* Gets the policy ID associated with the thing for which the snapshot was taken.
*
* @return an Optional containing the policyId, or an empty Optional if the policyId of the Thing is unknown.
*/
public Optional getPolicyId() {
return Optional.ofNullable(policyId);
}
@Override
public ThingId getEntityId() {
return thingId;
}
@Override
public String getPubSubTopic() {
return PUB_SUB_TOPIC;
}
@Override
protected ThingSnapshotTaken setDittoHeaders(final DittoHeaders dittoHeaders, final JsonObject thingJson) {
return newBuilder(thingId, getRevision(), getLifecycle(), thingJson)
.policyId(getPolicyId().orElse(null))
.timestamp(getTimestamp().orElse(null))
.metadata(getMetadata().orElse(null))
.dittoHeaders(dittoHeaders)
.build();
}
@Override
public String getResourceType() {
return RESOURCE_TYPE;
}
@Override
public JsonObject toJson(final JsonSchemaVersion schemaVersion, final Predicate predicate) {
var result = super.toJson(schemaVersion, predicate);
if (null != policyId) {
result = JsonFactory.newObjectBuilder(result)
.set(JSON_POLICY_ID, policyId.toString(), schemaVersion.and(predicate))
.build();
}
return result;
}
@Override
public boolean equals(@Nullable final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
final var that = (ThingSnapshotTaken) o;
return Objects.equals(thingId, that.thingId) && Objects.equals(policyId, that.policyId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), thingId, policyId);
}
@Override
public String toString() {
return getClass().getSimpleName() + " [" +
super.toString() +
", thingId=" + thingId +
", policyId=" + policyId +
"]";
}
/**
* A mutable builder with a fluent API for creating instances of {@code ThingSnapshotTaken}.
* By default the builder sets the timestamp of the event to {@link Instant#now()} and empty DittoHeaders.
* Both properties can be overwritten by calling the appropriate setter methods.
*/
@NotThreadSafe
public static final class Builder {
private final ThingId thingId;
private final long revisionNumber;
private final PersistenceLifecycle lifecycle;
private final JsonObject thingJson;
@Nullable private PolicyId policyId;
@Nullable private Instant timestamp;
@Nullable private Metadata metadata;
private DittoHeaders dittoHeaders;
private Builder(final ThingId thingId,
final long revisionNumber,
final PersistenceLifecycle lifecycle,
final JsonObject thingJson) {
this.thingId = thingId;
this.revisionNumber = revisionNumber;
this.lifecycle = lifecycle;
this.thingJson = thingJson;
policyId = null;
timestamp = Instant.now();
metadata = null;
dittoHeaders = DittoHeaders.empty();
}
/**
* Sets the specified policy ID.
*
* @param policyId the policy ID to be set or {@code null} if the event has none (default).
* @return this builder instance.
*/
public Builder policyId(@Nullable final PolicyId policyId) {
this.policyId = policyId;
return this;
}
/**
* Sets the timestamp when the snapshot was taken. By default the timestamp is set to {@link Instant#now()}.
*
* @param timestamp the timestamp to be set or {@code null} if the event does not have a timestamp at all.
* @return this builder instance.
*/
public Builder timestamp(@Nullable final Instant timestamp) {
this.timestamp = timestamp;
return this;
}
/**
* Sets the specified metadata.
*
* @param metadata the metadata to be set or {@code null} if the event has none (default).
* @return this builder instance.
*/
public Builder metadata(@Nullable final Metadata metadata) {
this.metadata = metadata;
return this;
}
/**
* Sets the specified DittoHeaders. By default empty headers are set.
*
* @param dittoHeaders the headers to be set.
* @return this builder instance.
* @throws NullPointerException if {@code dittoHeaders} is {@code null}.
*/
public Builder dittoHeaders(final DittoHeaders dittoHeaders) {
this.dittoHeaders = ConditionChecker.checkNotNull(dittoHeaders, "dittoHeaders");
return this;
}
/**
* Constructs a new {@code ThingSnapshotTaken} instance.
*
* @return the ThingSnapshotTaken instance.
*/
public ThingSnapshotTaken build() {
return new ThingSnapshotTaken(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy