Skip to content

Commit

Permalink
Issue #559: Added AddConnectionLogEntry.
Browse files Browse the repository at this point in the history
This class conveys a `LogEntry`. It is intended to be sent within Ditto cluster to connectivity shard region for adding the log entry to the connection log.

Signed-off-by: Juergen Fickel <juergen.fickel@bosch.io>
  • Loading branch information
Juergen Fickel committed Oct 29, 2021
1 parent 353f798 commit b653b36
Show file tree
Hide file tree
Showing 2 changed files with 306 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* 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.connectivity.model;

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

import java.text.MessageFormat;
import java.util.Objects;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import org.eclipse.ditto.base.model.json.FieldType;
import org.eclipse.ditto.base.model.json.JsonSchemaVersion;
import org.eclipse.ditto.base.model.json.Jsonifiable;
import org.eclipse.ditto.json.JsonFieldDefinition;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.json.JsonParseException;
import org.eclipse.ditto.json.JsonRuntimeException;

/**
* Transports a {@link LogEntry} that should be added to connection log.
*
* @since 2.2.0
*/
@Immutable
public final class AddConnectionLogEntry implements Jsonifiable<JsonObject> {

private final LogEntry logEntry;

private AddConnectionLogEntry(final LogEntry logEntry) {
this.logEntry = logEntry;
}

/**
* Returns a new instance of {@code AddConnectionLogEntry} for the specified {@code LogEntry} argument.
*
* @param connectionLogEntry the entry to be added to the connection log.
* @return the instance.
* @throws NullPointerException if {@code connectionLogEntry} is {@code null}.
*/
public static AddConnectionLogEntry of(final LogEntry connectionLogEntry) {
return new AddConnectionLogEntry(checkNotNull(connectionLogEntry, "connectionLogEntry"));
}

/**
* Deserializes an instance of {@code AddConnectionLogEntry} from the specified {@code JsonObject} argument.
*
* @param jsonObject the JSON object to be deserialized.
* @return the deserialized {@code AddConnectionLogEntry}.
* @throws NullPointerException if {@code jsonObject} is {@code null}.
* @throws org.eclipse.ditto.json.JsonMissingFieldException if {@code jsonObject} does not contain all required
* fields.
* @throws org.eclipse.ditto.json.JsonParseException if {@code jsonObject} cannot be deserialized because of
* invalid data.
*/
public static AddConnectionLogEntry fromJson(final JsonObject jsonObject) {
return new AddConnectionLogEntry(deserializeLogEntryOrThrow(checkNotNull(jsonObject, "jsonObject")));
}

private static LogEntry deserializeLogEntryOrThrow(final JsonObject jsonObject) {
final JsonFieldDefinition<JsonObject> fieldDefinition = JsonFields.LOG_ENTRY;
try {
return ConnectivityModelFactory.logEntryFromJson(jsonObject.getValueOrThrow(fieldDefinition));
} catch (final JsonRuntimeException e) {
throw JsonParseException.newBuilder()
.message(MessageFormat.format("Failed to deserialize value of key <{0}> as {1}: {2}",
fieldDefinition.getPointer(),
LogEntry.class.getName(),
e.getMessage()))
.cause(e)
.build();
}
}

/**
* Returns the entry to be added to the connection log.
*
* @return the connection log entry.
*/
public LogEntry getLogEntry() {
return logEntry;
}

@Override
public JsonObject toJson() {
return JsonObject.newBuilder()
.set(JsonFields.LOG_ENTRY, logEntry.toJson())
.build();
}

@Override
public boolean equals(@Nullable final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final AddConnectionLogEntry that = (AddConnectionLogEntry) o;
return logEntry.equals(that.logEntry);
}

@Override
public int hashCode() {
return Objects.hash(logEntry);
}

@Override
public String toString() {
return getClass().getSimpleName() + " [" +
"logEntry=" + logEntry +
"]";
}

/**
* Definitions of the fields an {@code AddConnectionLogEntry} JSON object representation.
*/
@Immutable
public static final class JsonFields {

/**
* Definition of a field containing the JSON object representation of the {@link LogEntry}.
*/
public static final JsonFieldDefinition<JsonObject> LOG_ENTRY =
JsonFieldDefinition.ofJsonObject("logEntry", FieldType.REGULAR, JsonSchemaVersion.V_2);

private JsonFields() {
throw new AssertionError();
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* 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.connectivity.model;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
import static org.mutabilitydetector.unittesting.AllowedReason.provided;
import static org.mutabilitydetector.unittesting.MutabilityAssert.assertInstancesOf;
import static org.mutabilitydetector.unittesting.MutabilityMatchers.areImmutable;

import java.time.Instant;

import org.eclipse.ditto.base.model.correlationid.TestNameCorrelationId;
import org.eclipse.ditto.json.JsonFactory;
import org.eclipse.ditto.json.JsonFieldDefinition;
import org.eclipse.ditto.json.JsonMissingFieldException;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.json.JsonParseException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import nl.jqno.equalsverifier.EqualsVerifier;

/**
* Unit test for {@link AddConnectionLogEntry}.
*/
public final class AddConnectionLogEntryTest {

@Rule
public final TestNameCorrelationId testNameCorrelationId = TestNameCorrelationId.newInstance();

private LogEntry logEntry;

@Before
public void before() {
logEntry = ConnectivityModelFactory.newLogEntryBuilder(testNameCorrelationId.getCorrelationId().toString(),
Instant.now(),
LogCategory.RESPONSE,
LogType.DROPPED,
LogLevel.FAILURE,
"Facere culpa et cum doloribus. Voluptas alias magni voluptatum.")
.build();
}

@Test
public void assertImmutability() {
assertInstancesOf(AddConnectionLogEntry.class, areImmutable(), provided(LogEntry.class).isAlsoImmutable());
}

@Test
public void testHashCodeAndEquals() {
EqualsVerifier.forClass(AddConnectionLogEntry.class)
.usingGetClass()
.verify();
}

@Test
public void getInstanceWithNullLogEntryThrowsException() {
assertThatNullPointerException()
.isThrownBy(() -> AddConnectionLogEntry.of(null))
.withMessage("The connectionLogEntry must not be null!")
.withNoCause();
}

@Test
public void getInstanceReturnsNotNull() {
final AddConnectionLogEntry instance = AddConnectionLogEntry.of(logEntry);

assertThat(instance).isNotNull();
}

@Test
public void getLogEntryReturnsExpected() {
final AddConnectionLogEntry underTest = AddConnectionLogEntry.of(logEntry);

assertThat(underTest.getLogEntry()).isEqualTo(logEntry);
}

@Test
public void toJsonReturnsExpected() {
final JsonObject jsonObject = JsonObject.newBuilder()
.set(AddConnectionLogEntry.JsonFields.LOG_ENTRY, logEntry.toJson())
.build();

final AddConnectionLogEntry underTest = AddConnectionLogEntry.of(logEntry);

assertThat(underTest.toJson()).isEqualTo(jsonObject);
}

@Test
public void fromJsonWithNullJsonObjectThrowsException() {
assertThatNullPointerException()
.isThrownBy(() -> AddConnectionLogEntry.fromJson(null))
.withMessage("The jsonObject must not be null!")
.withNoCause();
}

@Test
public void fromJsonWithValidJsonObjectReturnsExpected() {
final AddConnectionLogEntry addConnectionLogEntry = AddConnectionLogEntry.of(logEntry);

assertThat(AddConnectionLogEntry.fromJson(addConnectionLogEntry.toJson())).isEqualTo(addConnectionLogEntry);
}

@Test
public void fromJsonWithMissingJsonFieldThrowsException() {
final JsonObject invalidAddConnectionLogEntryJsonObject = JsonObject.newBuilder().set("foo", "bar").build();

assertThatExceptionOfType(JsonParseException.class)
.isThrownBy(() -> AddConnectionLogEntry.fromJson(invalidAddConnectionLogEntryJsonObject))
.withMessageStartingWith("Failed to deserialize value of key <%s> as %s:",
AddConnectionLogEntry.JsonFields.LOG_ENTRY.getPointer(),
LogEntry.class.getName())
.withCauseInstanceOf(JsonMissingFieldException.class);
}

@Test
public void fromJsonWithInvalidLogEntryValueTypeThrowsException() {
final JsonFieldDefinition<JsonObject> logEntryFieldDefinition = AddConnectionLogEntry.JsonFields.LOG_ENTRY;
final JsonObject invalidAddConnectionLogEntryJsonObject = JsonObject.newBuilder()
.set(logEntryFieldDefinition.getPointer(), "foo")
.build();

assertThatExceptionOfType(JsonParseException.class)
.isThrownBy(() -> AddConnectionLogEntry.fromJson(invalidAddConnectionLogEntryJsonObject))
.withMessageStartingWith("Failed to deserialize value of key <%s> as %s:",
logEntryFieldDefinition.getPointer(),
LogEntry.class.getName())
.withCauseInstanceOf(JsonParseException.class);
}

@Test
public void fromJsonWithCorruptedLogEntryValueThrowsException() {
final JsonFieldDefinition<JsonObject> logEntryFieldDefinition = AddConnectionLogEntry.JsonFields.LOG_ENTRY;
final JsonObject invalidLogEntryJsonObject = JsonFactory.newObjectBuilder(logEntry.toJson())
.set(LogEntry.JsonFields.LEVEL, "foo")
.build();
final JsonObject invalidAddConnectionLogEntryJsonObject = JsonObject.newBuilder()
.set(logEntryFieldDefinition, invalidLogEntryJsonObject)
.build();

assertThatExceptionOfType(JsonParseException.class)
.isThrownBy(() -> AddConnectionLogEntry.fromJson(invalidAddConnectionLogEntryJsonObject))
.withMessageStartingWith("Failed to deserialize value of key <%s> as %s:",
logEntryFieldDefinition.getPointer(),
LogEntry.class.getName())
.withCauseInstanceOf(JsonParseException.class);
}

}

0 comments on commit b653b36

Please sign in to comment.