Commit 408ce29d authored by Martin Grzenia's avatar Martin Grzenia
Browse files

Merge branch 'feature/device-registry-amqp-data-structures' into 'main'

Add AMQP related classes for the new device registration process

Closes SE-5484

See merge request silicon-economy/base/iotbroker/sdk!13
parents f497dd95 6c9a5125
......@@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [5.5.0] - 2022-03-30
### Added
- Introduce messages intended to be sent via AMQP that represent events emitted for changes to `org.siliconeconomy.iotbroker.model.device.DeviceInstance` and `org.siliconeconomy.iotbroker.model.device.DeviceType` instances.
- Add a configuration for the AMQP exchange where messages related to the new device registration process are published to.
## [5.4.1] - 2022-02-25
### Fixed
- Fix typo on an attribute of `DeviceInstance`.
......
......@@ -11,7 +11,7 @@
<groupId>org.siliconeconomy.iotbroker</groupId>
<artifactId>sdk</artifactId>
<version>5.4.1</version>
<version>5.5.0</version>
<licenses>
<license>
......
/*
* Copyright 2021 Open Logistics Foundation
*
* Licensed under the Open Logistics License 1.0.
* For details on the licensing terms, see the LICENSE file.
*/
package org.siliconeconomy.iotbroker.model.device;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.checkerframework.checker.nullness.qual.NonNull;
import static java.util.Objects.requireNonNull;
/**
* Represents an update event emitted for {@link DeviceInstance}s.
*
* @author M. Grzenia
* @author D. Ronnenberg
*/
@Getter
@EqualsAndHashCode
@ToString
public class DeviceInstanceUpdate {
/**
* The new state of the {@link DeviceInstance} for which this update event was created.
*/
private final DeviceInstance newState;
/**
* The old state of the {@link DeviceInstance} for which this update event was created.
*/
private final DeviceInstance oldState;
/**
* This update event's type.
*/
@NonNull
private final Type type;
/**
* Creates a new instance.
*
* @param newState The new state of the {@link DeviceInstance}.
* @param oldState The old state of the {@link DeviceInstance}.
* @param type The type of the update event.
* @throws IllegalArgumentException If either {@code newState} or {@code oldState} is
* {@code null} without {@code type} having the appropriate
* value.
*/
public DeviceInstanceUpdate(DeviceInstance newState,
DeviceInstance oldState,
@NonNull Type type) {
this.type = requireNonNull(type, "type");
if (newState == null && type != Type.DELETED) {
throw new IllegalArgumentException("newState is null but object has not been deleted.");
}
this.newState = newState;
if (oldState == null && type != Type.CREATED) {
throw new IllegalArgumentException("oldState is null but object has not been created.");
}
this.oldState = oldState;
}
/**
* Indicates the type of the update event.
*/
public enum Type {
/**
* Indicates that a {@link DeviceInstance} has been created.
*/
CREATED,
/**
* Indicates that a {@link DeviceInstance} has been modified.
*/
MODIFIED,
/**
* Indicates that a {@link DeviceInstance} has been deleted.
*/
DELETED;
}
}
/*
* Copyright 2021 Open Logistics Foundation
*
* Licensed under the Open Logistics License 1.0.
* For details on the licensing terms, see the LICENSE file.
*/
package org.siliconeconomy.iotbroker.model.device;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.checkerframework.checker.nullness.qual.NonNull;
import static java.util.Objects.requireNonNull;
/**
* Represents an update event emitted for {@link DeviceType}s.
*
* @author M. Grzenia
* @author D. Ronnenberg
*/
@Getter
@EqualsAndHashCode
@ToString
public class DeviceTypeUpdate {
/**
* The new state of the {@link DeviceType} for which this update event was created.
*/
private final DeviceType newState;
/**
* The old state of the {@link DeviceType} for which this update event was created.
*/
private final DeviceType oldState;
/**
* This update event's type.
*/
@NonNull
private final Type type;
/**
* Creates a new instance.
*
* @param newState The new state of the {@link DeviceType}.
* @param oldState The old state of the {@link DeviceType}.
* @param type The type of the update event.
* @throws IllegalArgumentException If either {@code newState} or {@code oldState} is
* {@code null} without {@code type} having the appropriate
* value.
*/
public DeviceTypeUpdate(DeviceType newState, DeviceType oldState, @NonNull Type type) {
this.type = requireNonNull(type, "type");
if (newState == null && type != Type.DELETED) {
throw new IllegalArgumentException("newState is null but object has not been deleted.");
}
this.newState = newState;
if (oldState == null && type != Type.CREATED) {
throw new IllegalArgumentException("oldState is null but object has not been created.");
}
this.oldState = oldState;
}
/**
* Indicates the type of the update event.
*/
public enum Type {
/**
* Indicates that a {@link DeviceType} has been created.
*/
CREATED,
/**
* Indicates that a {@link DeviceType} has been modified.
*/
MODIFIED,
/**
* Indicates that a {@link DeviceType} has been deleted.
*/
DELETED;
}
}
/*
* Copyright 2021 Open Logistics Foundation
*
* Licensed under the Open Logistics License 1.0.
* For details on the licensing terms, see the LICENSE file.
*/
package org.siliconeconomy.iotbroker.utils.amqp;
import com.rabbitmq.client.BuiltinExchangeType;
import org.siliconeconomy.iotbroker.model.device.DeviceInstanceUpdate;
import org.siliconeconomy.iotbroker.model.device.DeviceTypeUpdate;
/**
* Defines the configuration of the AMQP exchange where messages regarding the device management
* are published to. This includes the following message:
* <ul>
* <li>{@link DeviceInstanceUpdate}</li>
* <li>{@link DeviceTypeUpdate}</li>
* </ul>
*
* @author M. Grzenia
*/
public class DeviceManagementExchangeConfiguration {
/**
* The name of the exchange.
*/
public static final String NAME = "device.management";
/**
* The exchange type.
* Corresponds to {@link BuiltinExchangeType#TOPIC}.
*/
public static final String TYPE = "topic";
/**
* The exchange durability.
*/
public static final boolean DURABLE = true;
/**
* The format of the routing key used to publish {@link DeviceInstanceUpdate}s to the exchange.
* <p>
* The format is based on the following pattern:
* {@literal deviceInstance.<deviceTypeIdentifier>.update}
*
* @see #formatDeviceInstanceUpdateRoutingKey(String)
*/
public static final String ROUTING_KEY_DEVICE_INSTANCE_UPDATE_FORMAT = "deviceInstance.%s.update";
/**
* The format of the routing key used to publish {@link DeviceTypeUpdate}s to the exchange.
* <p>
* The format is based on the following pattern:
* {@literal deviceType.<deviceTypeIdentifier>.update}
*
* @see #formatDeviceTypeUpdateRoutingKey(String)
*/
public static final String ROUTING_KEY_DEVICE_TYPE_UPDATE_FORMAT = "deviceType.%s.update";
private DeviceManagementExchangeConfiguration() {
}
/**
* Convenience method for formatting the {@link #ROUTING_KEY_DEVICE_INSTANCE_UPDATE_FORMAT}.
*
* @param deviceTypeIdentifier The device type identifier to use.
* @return The formatted string.
*/
public static String formatDeviceInstanceUpdateRoutingKey(String deviceTypeIdentifier) {
return String.format(ROUTING_KEY_DEVICE_INSTANCE_UPDATE_FORMAT, deviceTypeIdentifier);
}
/**
* Convenience method for formatting the {@link #ROUTING_KEY_DEVICE_TYPE_UPDATE_FORMAT}.
*
* @param deviceTypeIdentifier The device type identifier to use.
* @return The formatted string.
*/
public static String formatDeviceTypeUpdateRoutingKey(String deviceTypeIdentifier) {
return String.format(ROUTING_KEY_DEVICE_TYPE_UPDATE_FORMAT, deviceTypeIdentifier);
}
}
/*
* Copyright 2021 Open Logistics Foundation
*
* Licensed under the Open Logistics License 1.0.
* For details on the licensing terms, see the LICENSE file.
*/
package org.siliconeconomy.iotbroker.model.device;
import org.junit.jupiter.api.Test;
import java.time.Instant;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.siliconeconomy.iotbroker.model.device.DeviceInstanceUpdate.Type.*;
/**
* Test cases for {@link DeviceInstanceUpdate}.
*
* @author M. Grzenia
*/
class DeviceInstanceUpdateTest {
@Test
void shouldSucceedObjectInstantiation() {
assertDoesNotThrow(() -> {
new DeviceInstanceUpdate(createDummyInstance(), null, CREATED);
new DeviceInstanceUpdate(createDummyInstance(), createDummyInstance(), MODIFIED);
new DeviceInstanceUpdate(null, createDummyInstance(), DELETED);
});
}
@Test
void shouldFailObjectInstantiation() {
assertThrows(
IllegalArgumentException.class,
() -> new DeviceInstanceUpdate(null, null, CREATED)
);
assertThrows(
IllegalArgumentException.class,
() -> new DeviceInstanceUpdate(null, null, MODIFIED)
);
assertThrows(
IllegalArgumentException.class,
() -> new DeviceInstanceUpdate(null, null, DELETED)
);
}
private DeviceInstance createDummyInstance() {
return new DeviceInstance("", "", "", "", Instant.now(),
Instant.EPOCH, false, "", "", "");
}
}
/*
* Copyright 2021 Open Logistics Foundation
*
* Licensed under the Open Logistics License 1.0.
* For details on the licensing terms, see the LICENSE file.
*/
package org.siliconeconomy.iotbroker.model.device;
import org.junit.jupiter.api.Test;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.siliconeconomy.iotbroker.model.device.DeviceTypeUpdate.Type.*;
/**
* Test cases for {@link DeviceTypeUpdate}.
*
* @author M. Grzenia
*/
class DeviceTypeUpdateTest {
@Test
void shouldSucceedObjectInstantiation() {
assertDoesNotThrow(() -> {
new DeviceTypeUpdate(createDummyInstance(), null, CREATED);
new DeviceTypeUpdate(createDummyInstance(), createDummyInstance(), MODIFIED);
new DeviceTypeUpdate(null, createDummyInstance(), DELETED);
});
}
@Test
void shouldFailObjectInstantiation() {
assertThrows(
IllegalArgumentException.class,
() -> new DeviceTypeUpdate(null, null, CREATED)
);
assertThrows(
IllegalArgumentException.class,
() -> new DeviceTypeUpdate(null, null, MODIFIED)
);
assertThrows(
IllegalArgumentException.class,
() -> new DeviceTypeUpdate(null, null, DELETED)
);
}
private DeviceType createDummyInstance() {
return new DeviceType("id", "", "", Set.of(), "", false, false, false);
}
}
/*
* Copyright 2021 Open Logistics Foundation
*
* Licensed under the Open Logistics License 1.0.
* For details on the licensing terms, see the LICENSE file.
*/
package org.siliconeconomy.iotbroker.utils.amqp;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* Test cases for {@link DeviceManagementExchangeConfiguration}.
*
* @author M. Grzenia
*/
class DeviceManagementExchangeConfigurationTest {
@Test
void formatDeviceInstanceUpdateRoutingKey() {
assertEquals(
"deviceInstance.myDeviceTypeIdentifier.update",
DeviceManagementExchangeConfiguration
.formatDeviceInstanceUpdateRoutingKey("myDeviceTypeIdentifier")
);
}
@Test
void formatDeviceTypeUpdateRoutingKey() {
assertEquals(
"deviceType.myDeviceTypeIdentifier.update",
DeviceManagementExchangeConfiguration
.formatDeviceTypeUpdateRoutingKey("myDeviceTypeIdentifier")
);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment