Skip to content

Commit db27293

Browse files
committed
eclipse-ditto#1843 add Migrated Command, enhance ThingMigrated Event
1 parent 3c7fe35 commit db27293

File tree

9 files changed

+56
-82
lines changed

9 files changed

+56
-82
lines changed

base/model/src/main/java/org/eclipse/ditto/base/model/signals/commands/Command.java

+5
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ enum Category {
150150
*/
151151
MERGE,
152152

153+
/**
154+
* Category of commands that change the state of entities.
155+
*/
156+
MIGRATE,
157+
153158
/**
154159
* Category of commands that delete entities.
155160
*/

protocol/src/main/java/org/eclipse/ditto/protocol/mapper/ThingMigratedEventSignalMapper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ final class ThingMigratedEventSignalMapper extends AbstractSignalMapper<ThingMig
2929
void enhancePayloadBuilder(final ThingMigrated signal, final PayloadBuilder payloadBuilder) {
3030
payloadBuilder.withRevision(signal.getRevision())
3131
.withTimestamp(signal.getTimestamp().orElse(null))
32-
.withValue(signal.getValue());
32+
.withValue(signal.getThing().toJson());
3333
}
3434

3535
@Override

protocol/src/main/java/org/eclipse/ditto/protocol/mappingstrategies/ThingMigratedEventMappingStrategies.java

+1-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import javax.annotation.Nullable;
1919

2020
import org.eclipse.ditto.json.JsonMissingFieldException;
21-
import org.eclipse.ditto.json.JsonPointer;
2221
import org.eclipse.ditto.base.model.entity.metadata.Metadata;
2322
import org.eclipse.ditto.protocol.Adaptable;
2423
import org.eclipse.ditto.protocol.JsonifiableMapper;
@@ -47,9 +46,7 @@ public JsonifiableMapper<ThingMigrated> find(final String type) {
4746

4847
private static ThingMigrated thingMigrated(final Adaptable adaptable) {
4948
return ThingMigrated.of(
50-
thingIdFrom(adaptable),
51-
JsonPointer.of(adaptable.getPayload().getPath().toString()),
52-
adaptable.getPayload().getValue().orElse(null),
49+
thingFrom(adaptable),
5350
revisionFrom(adaptable),
5451
timestampFrom(adaptable),
5552
dittoHeadersFrom(adaptable),

things/model/src/main/java/org/eclipse/ditto/things/model/signals/commands/modify/MigrateThingDefinition.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ private MigrateThingDefinition(final ThingId thingId,
7373
final Map<ResourceKey, String> patchConditions,
7474
final boolean initializeMissingPropertiesFromDefaults,
7575
final DittoHeaders dittoHeaders) {
76-
super(TYPE, FeatureToggle.checkMergeFeatureEnabled(TYPE, dittoHeaders));
76+
super(TYPE, dittoHeaders);
7777
this.thingId = checkNotNull(thingId, "thingId");
7878
this.thingDefinitionUrl = checkNotNull(thingDefinitionUrl, "thingDefinitionUrl");
7979
this.migrationPayload = checkJsonSize(checkNotNull(migrationPayload, "migrationPayload"), dittoHeaders);
@@ -185,7 +185,7 @@ public boolean changesAuthorization() {
185185

186186
@Override
187187
public Category getCategory() {
188-
return Category.MODIFY;
188+
return Category.MIGRATE;
189189
}
190190

191191
@Override

things/model/src/main/java/org/eclipse/ditto/things/model/signals/events/ThingEventToThingConverter.java

+1-10
Original file line numberDiff line numberDiff line change
@@ -122,16 +122,7 @@ private static Map<Class<?>, BiFunction<ThingEvent<?>, ThingBuilder.FromScratch,
122122
}
123123
);
124124
mappers.put(ThingMigrated.class,
125-
(te, tb) -> {
126-
final ThingMigrated thingMigrated = (ThingMigrated) te;
127-
final JsonPointer resourcePath = thingMigrated.getResourcePath();
128-
final JsonValue nonNullValue = filterNullValuesInJsonValue(thingMigrated.getValue());
129-
final JsonObject mergedFields = JsonFactory.newObject(resourcePath, nonNullValue);
130-
final JsonObject thingWithoutMergedFields = tb.build().toJson(FieldType.all());
131-
final JsonValue mergedJson = JsonFactory.mergeJsonValues(thingWithoutMergedFields, mergedFields);
132-
return ThingsModelFactory.newThing(mergedJson.asObject());
133-
}
134-
);
125+
(te, tb) -> ((ThingMigrated) te).getThing().toBuilder().setRevision(te.getRevision()).build());
135126
mappers.put(ThingDeleted.class,
136127
(te, tb) -> tb.build());
137128

things/model/src/main/java/org/eclipse/ditto/things/model/signals/events/ThingMigrated.java

+38-54
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
*/
1313
package org.eclipse.ditto.things.model.signals.events;
1414

15-
import static org.eclipse.ditto.base.model.common.ConditionChecker.checkNotNull;
1615

1716
import java.time.Instant;
1817
import java.util.Objects;
@@ -27,7 +26,6 @@
2726
import org.eclipse.ditto.base.model.json.FieldType;
2827
import org.eclipse.ditto.base.model.json.JsonParsableEvent;
2928
import org.eclipse.ditto.base.model.json.JsonSchemaVersion;
30-
import org.eclipse.ditto.base.model.signals.FeatureToggle;
3129
import org.eclipse.ditto.base.model.signals.UnsupportedSchemaVersionException;
3230
import org.eclipse.ditto.base.model.signals.commands.Command;
3331
import org.eclipse.ditto.base.model.signals.events.EventJsonDeserializer;
@@ -38,7 +36,8 @@
3836
import org.eclipse.ditto.json.JsonObjectBuilder;
3937
import org.eclipse.ditto.json.JsonPointer;
4038
import org.eclipse.ditto.json.JsonValue;
41-
import org.eclipse.ditto.things.model.ThingId;
39+
import org.eclipse.ditto.things.model.Thing;
40+
import org.eclipse.ditto.things.model.ThingsModelFactory;
4241

4342
/**
4443
* This event is emitted after a {@link org.eclipse.ditto.things.model.Thing} was successfully migrated.
@@ -59,44 +58,34 @@ public final class ThingMigrated extends AbstractThingEvent<ThingMigrated> imple
5958
*/
6059
public static final String TYPE = TYPE_PREFIX + NAME;
6160

62-
private final ThingId thingId;
63-
private final JsonPointer path;
64-
private final JsonValue value;
61+
private final Thing thing;
6562

66-
private ThingMigrated(final ThingId thingId,
67-
final JsonPointer path,
68-
final JsonValue value,
69-
final long revision,
70-
@Nullable final Instant timestamp,
71-
final DittoHeaders dittoHeaders,
72-
@Nullable final Metadata metadata) {
73-
super(TYPE, thingId, revision, timestamp, FeatureToggle.checkMergeFeatureEnabled(TYPE, dittoHeaders), metadata);
74-
this.thingId = checkNotNull(thingId, "thingId");
75-
this.path = checkNotNull(path, "path");
76-
this.value = checkNotNull(value, "value");
63+
private ThingMigrated(final Thing thing,
64+
final long revision,
65+
@Nullable final Instant timestamp,
66+
final DittoHeaders dittoHeaders,
67+
@Nullable final Metadata metadata) {
68+
super(TYPE, thing.getEntityId().orElseThrow(() -> new NullPointerException("Thing has no ID!")), revision, timestamp, dittoHeaders, metadata);
69+
this.thing = thing;
7770
checkSchemaVersion();
7871
}
7972

8073
/**
8174
* Creates an event of a migrated thing.
8275
*
83-
* @param thingId The thing ID.
84-
* @param path The path where the changes were applied.
85-
* @param value The value describing the changes that were migrated.
76+
* @param thing the created {@link org.eclipse.ditto.things.model.Thing}.
8677
* @param revision The revision number of the thing.
8778
* @param timestamp The event timestamp.
8879
* @param dittoHeaders The Ditto headers.
8980
* @param metadata The metadata associated with the event.
9081
* @return The created {@code ThingMigrated} event.
9182
*/
92-
public static ThingMigrated of(final ThingId thingId,
93-
final JsonPointer path,
94-
final JsonValue value,
83+
public static ThingMigrated of(final Thing thing,
9584
final long revision,
9685
@Nullable final Instant timestamp,
9786
final DittoHeaders dittoHeaders,
9887
@Nullable final Metadata metadata) {
99-
return new ThingMigrated(thingId, path, value, revision, timestamp, dittoHeaders, metadata);
88+
return new ThingMigrated(thing, revision, timestamp, dittoHeaders, metadata);
10089
}
10190

10291
/**
@@ -109,25 +98,23 @@ public static ThingMigrated of(final ThingId thingId,
10998
public static ThingMigrated fromJson(final JsonObject jsonObject, final DittoHeaders dittoHeaders) {
11099
return new EventJsonDeserializer<ThingMigrated>(TYPE, jsonObject).deserialize(
111100
(revision, timestamp, metadata) -> {
112-
final ThingId thingId = ThingId.of(jsonObject.getValueOrThrow(ThingEvent.JsonFields.THING_ID));
113-
final JsonPointer path = JsonPointer.of(jsonObject.getValueOrThrow(JsonFields.JSON_PATH));
114-
final JsonValue value = jsonObject.getValueOrThrow(JsonFields.JSON_VALUE);
101+
final JsonObject thingJsonObject = jsonObject.getValueOrThrow(ThingEvent.JsonFields.THING);
102+
final Thing extractedThing = ThingsModelFactory.newThing(thingJsonObject);
115103

116-
return of(thingId, path, value, revision, timestamp, dittoHeaders, metadata);
104+
return of(extractedThing, revision, timestamp, dittoHeaders, metadata);
117105
});
118106
}
119107

120108
@Override
121109
protected void appendPayload(final JsonObjectBuilder jsonObjectBuilder,
122-
final JsonSchemaVersion schemaVersion, final Predicate<JsonField> predicate) {
123-
jsonObjectBuilder.set(ThingEvent.JsonFields.THING_ID, thingId.toString(), predicate);
124-
jsonObjectBuilder.set(JsonFields.JSON_PATH, path.toString(), predicate);
125-
jsonObjectBuilder.set(JsonFields.JSON_VALUE, value, predicate);
110+
final JsonSchemaVersion schemaVersion, final Predicate<JsonField> thePredicate) {
111+
final Predicate<JsonField> predicate = schemaVersion.and(thePredicate);
112+
jsonObjectBuilder.set(ThingEvent.JsonFields.THING, thing.toJson(schemaVersion, thePredicate), predicate);
126113
}
127114

128115
@Override
129116
public ThingMigrated setDittoHeaders(final DittoHeaders dittoHeaders) {
130-
return of(thingId, path, value, getRevision(), getTimestamp().orElse(null), dittoHeaders,
117+
return of(thing, getRevision(), getTimestamp().orElse(null), dittoHeaders,
131118
getMetadata().orElse(null));
132119
}
133120

@@ -138,28 +125,26 @@ public Command.Category getCommandCategory() {
138125

139126
@Override
140127
public ThingMigrated setRevision(final long revision) {
141-
return of(thingId, path, value, revision, getTimestamp().orElse(null), getDittoHeaders(),
128+
return of(thing, revision, getTimestamp().orElse(null), getDittoHeaders(),
142129
getMetadata().orElse(null));
143130
}
144131

145-
@Override
146-
public JsonPointer getResourcePath() {
147-
return path;
148-
}
149-
150-
public JsonValue getValue() {
151-
return value;
132+
/**
133+
* @return the value describing the changes that were applied to the existing thing.
134+
*/
135+
public Thing getThing() {
136+
return thing;
152137
}
153138

154139
@Override
155-
public Optional<JsonValue> getEntity() {
156-
return Optional.of(value);
140+
public Optional<JsonValue> getEntity(final JsonSchemaVersion schemaVersion) {
141+
return Optional.of(thing.toJson(schemaVersion, FieldType.notHidden()));
157142
}
158143

159144
@Override
160145
public ThingMigrated setEntity(final JsonValue entity) {
161-
return of(thingId, path, entity, getRevision(), getTimestamp().orElse(null), getDittoHeaders(),
162-
getMetadata().orElse(null));
146+
return of(ThingsModelFactory.newThing(entity.asObject()), getRevision(), getTimestamp().orElse(null),
147+
getDittoHeaders(), getMetadata().orElse(null));
163148
}
164149

165150
@Override
@@ -186,23 +171,25 @@ public boolean equals(final Object o) {
186171
return false;
187172
}
188173
final ThingMigrated that = (ThingMigrated) o;
189-
return that.canEqual(this) && thingId.equals(that.thingId) &&
190-
path.equals(that.path) &&
191-
value.equals(that.value);
174+
return that.canEqual(this) && thing.equals(that.thing);
192175
}
193176

194177
@Override
195178
public int hashCode() {
196-
return Objects.hash(super.hashCode(), thingId, path, value);
179+
return Objects.hash(super.hashCode(), thing);
197180
}
198181
@Override
199182
public String toString() {
200183
return getClass().getSimpleName() + " [" + super.toString() +
201-
", path=" + path +
202-
", value=" + value +
184+
", thing=" + thing +
203185
"]";
204186
}
205187

188+
@Override
189+
public JsonPointer getResourcePath() {
190+
return JsonPointer.empty();
191+
}
192+
206193
/**
207194
* An enumeration of the JSON fields of a {@code ThingMigrated} event.
208195
*/
@@ -212,9 +199,6 @@ private JsonFields() {
212199
throw new AssertionError();
213200
}
214201

215-
public static final JsonFieldDefinition<String> JSON_PATH =
216-
JsonFactory.newStringFieldDefinition("path", FieldType.REGULAR, JsonSchemaVersion.V_2);
217-
218202
public static final JsonFieldDefinition<JsonValue> JSON_VALUE =
219203
JsonFactory.newJsonValueFieldDefinition("value", FieldType.REGULAR, JsonSchemaVersion.V_2);
220204
}

things/model/src/test/java/org/eclipse/ditto/things/model/signals/events/ThingMigratedTest.java

+5-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.eclipse.ditto.base.model.signals.events.EventsourcedEvent;
2222
import org.eclipse.ditto.json.JsonFactory;
2323
import org.eclipse.ditto.json.JsonObject;
24+
import org.eclipse.ditto.json.JsonPointer;
2425
import org.junit.Test;
2526

2627
import nl.jqno.equalsverifier.EqualsVerifier;
@@ -36,8 +37,7 @@ public final class ThingMigratedTest {
3637
.set(Event.JsonFields.METADATA, TestConstants.METADATA.toJson())
3738
.set(EventsourcedEvent.JsonFields.REVISION, TestConstants.Thing.REVISION_NUMBER)
3839
.set(ThingEvent.JsonFields.THING_ID, TestConstants.Thing.THING_ID.toString())
39-
.set(ThingMigrated.JsonFields.JSON_PATH, TestConstants.Thing.ABSOLUTE_LOCATION_ATTRIBUTE_POINTER.toString())
40-
.set(ThingMigrated.JsonFields.JSON_VALUE, TestConstants.Thing.LOCATION_ATTRIBUTE_VALUE)
40+
.set(ThingEvent.JsonFields.THING, TestConstants.Thing.THING.toJson())
4141
.build();
4242

4343
/**
@@ -60,14 +60,12 @@ public void testHashCodeAndEquals() {
6060
@Test
6161
public void toJsonReturnsExpected() {
6262
final ThingMigrated underTest =
63-
ThingMigrated.of(TestConstants.Thing.THING_ID,
64-
TestConstants.Thing.ABSOLUTE_LOCATION_ATTRIBUTE_POINTER,
65-
TestConstants.Thing.LOCATION_ATTRIBUTE_VALUE,
63+
ThingMigrated.of(TestConstants.Thing.THING,
6664
TestConstants.Thing.REVISION_NUMBER,
6765
TestConstants.TIMESTAMP,
6866
TestConstants.EMPTY_DITTO_HEADERS,
6967
TestConstants.METADATA);
70-
final JsonObject actualJson = underTest.toJson(FieldType.regularOrSpecial());
68+
final JsonObject actualJson = underTest.toJson(FieldType.notHidden());
7169

7270
assertThat(actualJson).isEqualTo(KNOWN_JSON);
7371
}
@@ -82,8 +80,7 @@ public void createInstanceFromValidJson() {
8280

8381
assertThat(underTest).isNotNull();
8482
assertThat((Object) underTest.getEntityId()).isEqualTo(TestConstants.Thing.THING_ID);
85-
assertThat(underTest.getResourcePath()).isEqualTo(TestConstants.Thing.ABSOLUTE_LOCATION_ATTRIBUTE_POINTER);
86-
assertThat(underTest.getValue()).isEqualTo(TestConstants.Thing.LOCATION_ATTRIBUTE_VALUE);
83+
assertThat(underTest.getResourcePath()).isEqualTo(JsonPointer.empty());
8784
assertThat(underTest.getMetadata()).contains(TestConstants.METADATA);
8885
assertThat(underTest.getRevision()).isEqualTo(TestConstants.Thing.REVISION_NUMBER);
8986
assertThat(underTest.getTimestamp()).contains(TestConstants.TIMESTAMP);

things/service/src/main/java/org/eclipse/ditto/things/service/persistence/actors/strategies/commands/MigrateThingDefinitionStrategy.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ private Result<ThingEvent<?>> handleMigrateDefinition(
117117

118118
final DittoHeaders dittoHeaders = command.getDittoHeaders();
119119
final boolean isDryRun = dittoHeaders.isDryRun();
120-
final JsonPointer path = JsonPointer.empty();
121120

122121
// 1. Evaluate Patch Conditions and modify the migrationPayload
123122
final JsonObject adjustedMigrationPayload = evaluatePatchConditions(
@@ -153,7 +152,7 @@ private Result<ThingEvent<?>> handleMigrateDefinition(
153152

154153
// 4. Apply migration and generate event
155154
final CompletionStage<ThingEvent<?>> eventStage = validatedStage.thenApply(pair -> ThingMigrated.of(
156-
pair.second().getEntityId(), path, pair.first().toJson(), nextRevision, eventTs, dittoHeaders,
155+
pair.first(), nextRevision, eventTs, dittoHeaders,
157156
metadata));
158157

159158
final CompletionStage<WithDittoHeaders> responseStage = validatedStage.thenApply(pair ->
@@ -337,6 +336,7 @@ private Thing applyMigrationPayload(final Context<ThingId> context, final Thing
337336
() -> dittoHeaders);
338337

339338
return ThingsModelFactory.newThingBuilder(mergedJson)
339+
.setId(context.getState())
340340
.setModified(eventTs)
341341
.setRevision(nextRevision)
342342
.build();

things/service/src/main/java/org/eclipse/ditto/things/service/persistence/actors/strategies/events/ThingMigratedStrategy.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ final class ThingMigratedStrategy extends AbstractThingEventStrategy<ThingMigrat
3838
public Thing handle(final ThingMigrated event, @Nullable final Thing thing, final long revision) {
3939
if (null != thing) {
4040
final JsonObject jsonObject = thing.toJson(FieldType.all());
41-
final JsonObject mergePatch = JsonFactory.newObject(event.getResourcePath(), event.getValue());
41+
final JsonObject mergePatch = event.getThing().toJson();
4242
final JsonObject mergedJson = JsonFactory.mergeJsonValues(mergePatch, jsonObject).asObject();
4343
return ThingsModelFactory.newThingBuilder(mergedJson)
4444
.setRevision(revision)

0 commit comments

Comments
 (0)