test: bootstrap wcs demo domain
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
package com.ft546.wcs.demo.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public final class DispatchQueueEntry {
|
||||
public enum QueueType {
|
||||
BUSINESS,
|
||||
AVOIDANCE
|
||||
}
|
||||
|
||||
private final String queueId;
|
||||
private final String taskId;
|
||||
private final String vehicleId;
|
||||
private final QueueType queueType;
|
||||
private final String startSite;
|
||||
private final String endSite;
|
||||
private final int priority;
|
||||
private int issued;
|
||||
private int executionStatus;
|
||||
private List<String> path;
|
||||
|
||||
private DispatchQueueEntry(
|
||||
String queueId,
|
||||
String taskId,
|
||||
String vehicleId,
|
||||
QueueType queueType,
|
||||
String startSite,
|
||||
String endSite,
|
||||
int priority
|
||||
) {
|
||||
this.queueId = queueId;
|
||||
this.taskId = taskId;
|
||||
this.vehicleId = vehicleId;
|
||||
this.queueType = queueType;
|
||||
this.startSite = startSite;
|
||||
this.endSite = endSite;
|
||||
this.priority = priority;
|
||||
this.issued = 0;
|
||||
this.executionStatus = 1;
|
||||
this.path = Collections.emptyList();
|
||||
}
|
||||
|
||||
public static DispatchQueueEntry business(DispatchTask task, String vehicleId) {
|
||||
if (task == null) {
|
||||
throw new IllegalArgumentException("task must not be null");
|
||||
}
|
||||
if (vehicleId == null || vehicleId.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("vehicle id must not be blank");
|
||||
}
|
||||
return new DispatchQueueEntry(
|
||||
task.getTaskId(),
|
||||
task.getTaskId(),
|
||||
vehicleId,
|
||||
QueueType.BUSINESS,
|
||||
task.getSourceSite(),
|
||||
task.getTargetSite(),
|
||||
task.getPriority()
|
||||
);
|
||||
}
|
||||
|
||||
public void markIssued(List<String> issuedPath) {
|
||||
if (issued != 0) {
|
||||
throw new IllegalStateException("queue has already been issued");
|
||||
}
|
||||
if (issuedPath == null || issuedPath.isEmpty()) {
|
||||
throw new IllegalArgumentException("issued path must not be empty");
|
||||
}
|
||||
this.path = Collections.unmodifiableList(new ArrayList<String>(issuedPath));
|
||||
this.issued = 1;
|
||||
this.executionStatus = 3;
|
||||
}
|
||||
|
||||
public void markCompleted() {
|
||||
if (issued == 0) {
|
||||
throw new IllegalStateException("unissued queue cannot complete");
|
||||
}
|
||||
this.executionStatus = 4;
|
||||
}
|
||||
|
||||
public String getQueueId() {
|
||||
return queueId;
|
||||
}
|
||||
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public String getVehicleId() {
|
||||
return vehicleId;
|
||||
}
|
||||
|
||||
public QueueType getQueueType() {
|
||||
return queueType;
|
||||
}
|
||||
|
||||
public String getStartSite() {
|
||||
return startSite;
|
||||
}
|
||||
|
||||
public String getEndSite() {
|
||||
return endSite;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public int getIssued() {
|
||||
return issued;
|
||||
}
|
||||
|
||||
public int getExecutionStatus() {
|
||||
return executionStatus;
|
||||
}
|
||||
|
||||
public boolean isIssued() {
|
||||
return issued == 1;
|
||||
}
|
||||
|
||||
public List<String> getPath() {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.ft546.wcs.demo.model;
|
||||
|
||||
public final class DispatchTask {
|
||||
public enum TaskType {
|
||||
INBOUND,
|
||||
OUTBOUND,
|
||||
RELOCATION
|
||||
}
|
||||
|
||||
private final String taskId;
|
||||
private final TaskType type;
|
||||
private final String sourceSite;
|
||||
private final String targetSite;
|
||||
private final int floor;
|
||||
private final int priority;
|
||||
|
||||
public DispatchTask(
|
||||
String taskId,
|
||||
TaskType type,
|
||||
String sourceSite,
|
||||
String targetSite,
|
||||
int floor,
|
||||
int priority
|
||||
) {
|
||||
this.taskId = requireText(taskId, "task id");
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("task type must not be null");
|
||||
}
|
||||
this.type = type;
|
||||
this.sourceSite = requireText(sourceSite, "source site");
|
||||
this.targetSite = requireText(targetSite, "target site");
|
||||
if (floor <= 0) {
|
||||
throw new IllegalArgumentException("floor must be positive");
|
||||
}
|
||||
this.floor = floor;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public TaskType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getSourceSite() {
|
||||
return sourceSite;
|
||||
}
|
||||
|
||||
public String getTargetSite() {
|
||||
return targetSite;
|
||||
}
|
||||
|
||||
public int getFloor() {
|
||||
return floor;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
private static String requireText(String value, String name) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException(name + " must not be blank");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
66
javaTest/src/main/java/com/ft546/wcs/demo/model/Site.java
Normal file
66
javaTest/src/main/java/com/ft546/wcs/demo/model/Site.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package com.ft546.wcs.demo.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class Site {
|
||||
private final String id;
|
||||
private final int floor;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final String channel;
|
||||
|
||||
public Site(String id, int floor, int x, int y, String channel) {
|
||||
this.id = requireText(id, "site id");
|
||||
if (floor <= 0) {
|
||||
throw new IllegalArgumentException("floor must be positive");
|
||||
}
|
||||
this.floor = floor;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.channel = requireText(channel, "channel");
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getFloor() {
|
||||
return floor;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public String getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
private static String requireText(String value, String name) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException(name + " must not be blank");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof Site)) {
|
||||
return false;
|
||||
}
|
||||
Site site = (Site) other;
|
||||
return id.equals(site.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.ft546.wcs.demo.model;
|
||||
|
||||
public final class VehicleSnapshot {
|
||||
private final String vehicleId;
|
||||
private final int floor;
|
||||
private final String currentSite;
|
||||
private final int workMode;
|
||||
private final int status;
|
||||
private final int battery;
|
||||
private final boolean connected;
|
||||
private final boolean allowSend;
|
||||
private final boolean cargo;
|
||||
|
||||
public VehicleSnapshot(
|
||||
String vehicleId,
|
||||
int floor,
|
||||
String currentSite,
|
||||
int workMode,
|
||||
int status,
|
||||
int battery,
|
||||
boolean connected,
|
||||
boolean allowSend,
|
||||
boolean cargo
|
||||
) {
|
||||
this.vehicleId = requireText(vehicleId, "vehicle id");
|
||||
if (floor <= 0) {
|
||||
throw new IllegalArgumentException("floor must be positive");
|
||||
}
|
||||
this.floor = floor;
|
||||
this.currentSite = requireText(currentSite, "current site");
|
||||
this.workMode = workMode;
|
||||
this.status = status;
|
||||
if (battery < 0 || battery > 100) {
|
||||
throw new IllegalArgumentException("battery must be between 0 and 100");
|
||||
}
|
||||
this.battery = battery;
|
||||
this.connected = connected;
|
||||
this.allowSend = allowSend;
|
||||
this.cargo = cargo;
|
||||
}
|
||||
|
||||
public String getVehicleId() {
|
||||
return vehicleId;
|
||||
}
|
||||
|
||||
public int getFloor() {
|
||||
return floor;
|
||||
}
|
||||
|
||||
public String getCurrentSite() {
|
||||
return currentSite;
|
||||
}
|
||||
|
||||
public int getWorkMode() {
|
||||
return workMode;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public int getBattery() {
|
||||
return battery;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
public boolean isAllowSend() {
|
||||
return allowSend;
|
||||
}
|
||||
|
||||
public boolean isCargo() {
|
||||
return cargo;
|
||||
}
|
||||
|
||||
public VehicleSnapshot at(String siteId, int newFloor) {
|
||||
return new VehicleSnapshot(
|
||||
vehicleId,
|
||||
newFloor,
|
||||
siteId,
|
||||
workMode,
|
||||
status,
|
||||
battery,
|
||||
connected,
|
||||
allowSend,
|
||||
cargo
|
||||
);
|
||||
}
|
||||
|
||||
private static String requireText(String value, String name) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException(name + " must not be blank");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.ft546.wcs.demo;
|
||||
|
||||
import com.ft546.wcs.demo.model.DispatchQueueEntry;
|
||||
import com.ft546.wcs.demo.model.DispatchTask;
|
||||
import com.ft546.wcs.demo.model.Site;
|
||||
import com.ft546.wcs.demo.model.VehicleSnapshot;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class QueueLifecycleTest {
|
||||
|
||||
@Test
|
||||
void queueUsesLegacyLifecycleCodes() {
|
||||
DispatchTask task = new DispatchTask(
|
||||
"T-1",
|
||||
DispatchTask.TaskType.OUTBOUND,
|
||||
"A",
|
||||
"B",
|
||||
1,
|
||||
2
|
||||
);
|
||||
DispatchQueueEntry queue = DispatchQueueEntry.business(task, "1");
|
||||
|
||||
assertEquals(0, queue.getIssued());
|
||||
assertEquals(1, queue.getExecutionStatus());
|
||||
|
||||
queue.markIssued(Arrays.asList("A", "B"));
|
||||
|
||||
assertEquals(1, queue.getIssued());
|
||||
assertEquals(3, queue.getExecutionStatus());
|
||||
|
||||
queue.markCompleted();
|
||||
|
||||
assertEquals(4, queue.getExecutionStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
void queueCopiesPathAndRejectsCompletionBeforeIssue() {
|
||||
DispatchTask task = new DispatchTask(
|
||||
"T-2",
|
||||
DispatchTask.TaskType.INBOUND,
|
||||
"A",
|
||||
"B",
|
||||
1,
|
||||
2
|
||||
);
|
||||
DispatchQueueEntry queue = DispatchQueueEntry.business(task, "1");
|
||||
List<String> path = new java.util.ArrayList<String>(Arrays.asList("A", "B"));
|
||||
|
||||
assertThrows(IllegalStateException.class, queue::markCompleted);
|
||||
|
||||
queue.markIssued(path);
|
||||
path.add("C");
|
||||
|
||||
assertEquals(Arrays.asList("A", "B"), queue.getPath());
|
||||
assertThrows(UnsupportedOperationException.class, () -> queue.getPath().add("D"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void domainInputsRejectInvalidValues() {
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new Site("", 1, 0, 0, "C1"));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new VehicleSnapshot("1", 1, "A", 5, 1, 101, true, true, false));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new DispatchTask("", DispatchTask.TaskType.OUTBOUND, "A", "B", 1, 2));
|
||||
|
||||
VehicleSnapshot snapshot = new VehicleSnapshot(
|
||||
"1", 1, "A", 5, 1, 80, true, true, false
|
||||
);
|
||||
assertTrue(snapshot.isConnected());
|
||||
assertEquals("1", snapshot.getVehicleId());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user