Assigned either through the {@linkplain #AbstractEntity(Object) constructor which * accepts the ID}, or via {@link #setId(Object)}. Is never {@code null}. + * + * @apiNote The field is named with the underscore prefix to avoid + * name clash with the extension property name in Kotlin. */ - private @MonotonicNonNull I id; + @SuppressWarnings("FieldNamingConvention") // See `apiNote` above. + private @MonotonicNonNull I _id; /** Cached version of string ID. */ @LazyInit @@ -117,14 +121,26 @@ public abstract class AbstractEntity> *
Lazily initialized to the {@linkplain #defaultState() default state}, * if {@linkplain #state() accessed} before {@linkplain #setState(EntityState)} * initialization}. + * + * @apiNote The field is named with the underscore prefix to avoid + * name clash with the extension property name in Kotlin. */ + @SuppressWarnings("FieldNamingConvention") // See `apiNote` above. @LazyInit - private volatile @MonotonicNonNull S state; + private volatile @MonotonicNonNull S _state; - /** The version of the entity. */ - private volatile Version version; + /** + * The version of the entity. + * + * @apiNote The field is named with the underscore prefix to avoid + * name clash with the extension property name in Kotlin. + */ + @SuppressWarnings("FieldNamingConvention") // See `apiNote` above. + private volatile Version _version; - /** The lifecycle flags of the entity. */ + /** + * The lifecycle flags of the entity. + */ private volatile @MonotonicNonNull LifecycleFlags lifecycleFlags; /** @@ -135,9 +151,16 @@ public abstract class AbstractEntity> */ private volatile boolean lifecycleFlagsChanged; + /** + * A context for the logging operations performed by the entity in a receptor. + * + *
This field is {@code null}, if the entity is not being accessed through a receptor.
+ *
+ * @see #beforeInvoke(Receptor)
+ * @see #afterInvoke(Receptor)
+ */
private @Nullable AutoCloseable loggingContext = null;
-
/**
* Creates a new instance with the zero version and cleared lifecycle flags.
*
@@ -163,12 +186,12 @@ protected AbstractEntity(I id) {
@SuppressWarnings("InstanceVariableUsedBeforeInitialized") // checked in `if`
final void setId(I id) {
checkNotNull(id);
- if (this.id != null) {
- checkState(id.equals(this.id),
+ if (this._id != null) {
+ checkState(id.equals(this._id),
"Entity ID already assigned to `%s`." +
- " Attempted to reassign to `%s`.", this.id, id);
+ " Attempted to reassign to `%s`.", this._id, id);
}
- this.id = id;
+ this._id = id;
}
/**
@@ -188,7 +211,7 @@ protected AbstractEntity(I id, Function defaultState) {
@Override
public I id() {
- return checkNotNull(id);
+ return checkNotNull(_id);
}
/**
@@ -202,13 +225,13 @@ public I id() {
@Override
public final S state() {
ensureAccessToState();
- var result = state;
+ var result = _state;
if (result == null) {
synchronized (this) {
- result = state;
+ result = _state;
if (result == null) {
- state = defaultState();
- result = state;
+ _state = defaultState();
+ result = _state;
}
}
}
@@ -264,7 +287,7 @@ public EntityClass> modelClass() {
* Sets the entity state to the passed value.
*/
void setState(S newState) {
- this.state = checkNotNull(newState);
+ this._state = checkNotNull(newState);
}
/**
@@ -493,7 +516,7 @@ protected int versionNumber() {
final void updateVersion(Version newVersion) {
checkNotNull(newVersion);
check(newVersion);
- if (version.equals(newVersion)) {
+ if (_version.equals(newVersion)) {
return;
}
var currentVersionNumber = versionNumber();
@@ -525,7 +548,7 @@ void incrementState(S newState) {
}
void setVersion(Version version) {
- this.version = version;
+ this._version = version;
}
private Version incrementedVersion() {
@@ -540,7 +563,7 @@ private Version incrementedVersion() {
*/
@Override
public Version version() {
- return version;
+ return _version;
}
/**
@@ -550,14 +573,14 @@ public Version version() {
*/
int incrementVersion() {
setVersion(incrementedVersion());
- return version.getNumber();
+ return _version.getNumber();
}
/**
* Obtains timestamp of the entity version.
*/
public Timestamp whenModified() {
- return version.getTimestamp();
+ return _version.getTimestamp();
}
/**
diff --git a/server/src/main/kotlin/io/spine/server/ServerEnvironmentExtensions.kt b/server/src/main/kotlin/io/spine/server/ServerEnvironmentExts.kt
similarity index 89%
rename from server/src/main/kotlin/io/spine/server/ServerEnvironmentExtensions.kt
rename to server/src/main/kotlin/io/spine/server/ServerEnvironmentExts.kt
index 55a636b511..3b6fe330b4 100644
--- a/server/src/main/kotlin/io/spine/server/ServerEnvironmentExtensions.kt
+++ b/server/src/main/kotlin/io/spine/server/ServerEnvironmentExts.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2022, TeamDev. All rights reserved.
+ * Copyright 2023, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,8 +44,9 @@ import io.spine.environment.EnvironmentType
* }
* ```
*
- * @apiNote This function allows to avoid calling [ServerEnvironment.when] from Kotlin, which
- * requires backticking `when` because it is a reserved word.
+ * ### API NOTE
+ * This function allows to avoid calling [ServerEnvironment.when] from Kotlin, which
+ * requires backticking `"when"` because it is a reserved word.
*/
public inline fun >
+ E.id: I
+ get() = id()
+
+/**
+ * Obtains the entity version.
+ *
+ * This is a shortcut for `version()`.
+ *
+ * @param I the type of the entity identifiers.
+ * @param E the type of the transactional entity.
+ * @param S the type of the entity state.
+ * @param B the type of the entity state builder.
+ */
+public val , S : EntityState, B : ValidatingBuilder>
+ E.version: Version
+ get() = version()
+
+/**
+ * Obtains the entity state.
+ *
+ * This is a shortcut for `state()`.
+ *
+ * @param I the type of the entity identifiers.
+ * @param E the type of the transactional entity.
+ * @param S the type of the entity state.
+ * @param B the type of the entity state builder.
+ */
+public val , S : EntityState, B : ValidatingBuilder>
+ E.state: S
+ get() = state()
diff --git a/server/src/test/kotlin/io/spine/server/entity/TransactionalEntityExtensionsSpec.kt b/server/src/test/kotlin/io/spine/server/entity/TransactionalEntityExtensionsSpec.kt
index 877fc17951..b4c3bc1b38 100644
--- a/server/src/test/kotlin/io/spine/server/entity/TransactionalEntityExtensionsSpec.kt
+++ b/server/src/test/kotlin/io/spine/server/entity/TransactionalEntityExtensionsSpec.kt
@@ -37,17 +37,29 @@ internal class TransactionalEntityExtensionsSpec {
@Test
fun `add 'update' block handler for passing properties to 'builder'`() {
val entity = createEntity()
+ val prevVersion = entity.version
+ val prevId = entity.id
val str = randomString()
- entity.applyUpdate(str)
+
+ entity.doUpdate(str)
+
entity.value() shouldBe str
+ entity.version.isIncrement(prevVersion) shouldBe true
+ entity.id shouldBe prevId
}
@Test
fun `add 'alter' block handler for passing properties to 'builder'`() {
val entity = createEntity()
+ val prevVersion = entity.version
+ val prevId = entity.id
val str = randomString()
- entity.txApplyAlteration(str)
+
+ entity.doAlter(str)
+
entity.value() shouldBe str
+ entity.version.isIncrement(prevVersion) shouldBe true
+ entity.id shouldBe prevId
}
}
@@ -64,8 +76,8 @@ private fun createEntity() : Fixture {
}
/**
- * An entity which uses the [TransactionalEntity] extension functions in its [applyUpdate]
- * and [applyAlteration] methods.
+ * An entity which uses the [TransactionalEntity] extension functions in its [doUpdate]
+ * and [doAlter] methods.
*/
private class Fixture : TransactionalEntity