Added new model.
This commit is contained in:
parent
e8cb22276a
commit
2fbc22af0d
2
pom.xml
2
pom.xml
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>2.6.0</version>
|
<version>2.6.6</version>
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>nl.andrewl</groupId>
|
<groupId>nl.andrewl</groupId>
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.dao;
|
|
||||||
|
|
||||||
import nl.andrewl.railsignalapi.model.Branch;
|
|
||||||
import nl.andrewl.railsignalapi.model.RailSystem;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface BranchRepository extends JpaRepository<Branch, Long> {
|
|
||||||
Optional<Branch> findByIdAndRailSystem(long id, RailSystem railSystem);
|
|
||||||
Optional<Branch> findByIdAndRailSystemId(long id, long railSystemId);
|
|
||||||
Optional<Branch> findByNameAndRailSystem(String name, RailSystem railSystem);
|
|
||||||
List<Branch> findAllByRailSystemOrderByName(RailSystem railSystem);
|
|
||||||
List<Branch> findAllByNameAndRailSystem(String name, RailSystem railSystem);
|
|
||||||
}
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package nl.andrewl.railsignalapi.dao;
|
||||||
|
|
||||||
|
import nl.andrewl.railsignalapi.model.RailSystem;
|
||||||
|
import nl.andrewl.railsignalapi.model.component.Component;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ComponentRepository extends JpaRepository<Component, Long> {
|
||||||
|
void deleteAllByRailSystem(RailSystem rs);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package nl.andrewl.railsignalapi.dao;
|
||||||
|
|
||||||
|
import nl.andrewl.railsignalapi.model.RailSystem;
|
||||||
|
import nl.andrewl.railsignalapi.model.Segment;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface SegmentRepository extends JpaRepository<Segment, Long> {
|
||||||
|
void deleteAllByRailSystem(RailSystem rs);
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.dao;
|
|
||||||
|
|
||||||
import nl.andrewl.railsignalapi.model.SignalBranchConnection;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface SignalBranchConnectionRepository extends JpaRepository<SignalBranchConnection, Long> {
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.dao;
|
|
||||||
|
|
||||||
import nl.andrewl.railsignalapi.model.Branch;
|
|
||||||
import nl.andrewl.railsignalapi.model.RailSystem;
|
|
||||||
import nl.andrewl.railsignalapi.model.Signal;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface SignalRepository extends JpaRepository<Signal, Long> {
|
|
||||||
Optional<Signal> findByIdAndRailSystem(long id, RailSystem railSystem);
|
|
||||||
Optional<Signal> findByIdAndRailSystemId(long id, long railSystemId);
|
|
||||||
boolean existsByNameAndRailSystem(String name, RailSystem railSystem);
|
|
||||||
|
|
||||||
@Query("SELECT DISTINCT s FROM Signal s " +
|
|
||||||
"LEFT JOIN s.branchConnections bc " +
|
|
||||||
"WHERE bc.branch = :branch " +
|
|
||||||
"ORDER BY s.name")
|
|
||||||
List<Signal> findAllConnectedToBranch(Branch branch);
|
|
||||||
|
|
||||||
List<Signal> findAllByRailSystemOrderByName(RailSystem railSystem);
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.dao;
|
|
||||||
|
|
||||||
import nl.andrewl.railsignalapi.model.Train;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface TrainRepository extends JpaRepository<Train, Long> {
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public class Branch {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
|
||||||
private RailSystem railSystem;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
@Setter
|
|
||||||
private BranchStatus status;
|
|
||||||
|
|
||||||
@OneToMany(mappedBy = "branch", orphanRemoval = true)
|
|
||||||
private Set<SignalBranchConnection> signalConnections;
|
|
||||||
|
|
||||||
public Branch(RailSystem railSystem, String name, BranchStatus status) {
|
|
||||||
this.railSystem = railSystem;
|
|
||||||
this.name = name;
|
|
||||||
this.status = status;
|
|
||||||
this.signalConnections = new HashSet<>();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.model;
|
|
||||||
|
|
||||||
public enum BranchStatus {
|
|
||||||
FREE,
|
|
||||||
OCCUPIED
|
|
||||||
}
|
|
|
@ -1,5 +1,8 @@
|
||||||
package nl.andrewl.railsignalapi.model;
|
package nl.andrewl.railsignalapi.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cardinal direction, useful for some components.
|
||||||
|
*/
|
||||||
public enum Direction {
|
public enum Direction {
|
||||||
NORTH,
|
NORTH,
|
||||||
SOUTH,
|
SOUTH,
|
||||||
|
|
|
@ -8,6 +8,9 @@ import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a closed system that contains a collection of components.
|
||||||
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Getter
|
@Getter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@ -16,6 +19,9 @@ public class RailSystem {
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this system.
|
||||||
|
*/
|
||||||
@Column(nullable = false, unique = true)
|
@Column(nullable = false, unique = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package nl.andrewl.railsignalapi.model;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import nl.andrewl.railsignalapi.model.component.SegmentBoundaryNode;
|
||||||
|
import nl.andrewl.railsignalapi.model.component.Signal;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a traversable segment of a rail system that components can
|
||||||
|
* connect to.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
|
@Getter
|
||||||
|
public class Segment {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||||
|
private RailSystem railSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unique name for this segment.
|
||||||
|
*/
|
||||||
|
@Column(unique = true)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signals that are connected to this branch.
|
||||||
|
*/
|
||||||
|
@OneToMany(mappedBy = "segment")
|
||||||
|
private Set<Signal> signals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of nodes from which trains can enter and exit this segment.
|
||||||
|
*/
|
||||||
|
@ManyToMany(mappedBy = "segments", cascade = CascadeType.ALL)
|
||||||
|
private Set<SegmentBoundaryNode> boundaryNodes;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == this) return true;
|
||||||
|
return o instanceof Segment s && this.id != null && this.id.equals(s.id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,40 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Getter
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class Signal {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
|
||||||
private RailSystem railSystem;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@OneToMany(mappedBy = "signal", orphanRemoval = true, cascade = CascadeType.ALL)
|
|
||||||
private Set<SignalBranchConnection> branchConnections;
|
|
||||||
|
|
||||||
@Embedded
|
|
||||||
private Position position;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
@Setter
|
|
||||||
private boolean online = false;
|
|
||||||
|
|
||||||
public Signal(RailSystem railSystem, String name, Position position, Set<SignalBranchConnection> branchConnections) {
|
|
||||||
this.railSystem = railSystem;
|
|
||||||
this.name = name;
|
|
||||||
this.position = position;
|
|
||||||
this.branchConnections = branchConnections;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public class SignalBranchConnection implements Comparable<SignalBranchConnection> {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@ManyToOne(optional = false)
|
|
||||||
private Signal signal;
|
|
||||||
|
|
||||||
@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
|
|
||||||
private Branch branch;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
private Direction direction;
|
|
||||||
|
|
||||||
@ManyToMany
|
|
||||||
private Set<SignalBranchConnection> reachableSignalConnections;
|
|
||||||
|
|
||||||
public SignalBranchConnection(Signal signal, Branch branch, Direction direction) {
|
|
||||||
this.signal = signal;
|
|
||||||
this.branch = branch;
|
|
||||||
this.direction = direction;
|
|
||||||
reachableSignalConnections = new HashSet<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
return this.id != null &&
|
|
||||||
o instanceof SignalBranchConnection sbc && sbc.getId() != null &&
|
|
||||||
this.id.equals(sbc.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hashCode(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(SignalBranchConnection o) {
|
|
||||||
int c = Long.compare(this.getSignal().getId(), o.getSignal().getId());
|
|
||||||
if (c != 0) return c;
|
|
||||||
return this.direction.compareTo(o.getDirection());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Getter
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class Switch {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
|
||||||
private RailSystem railSystem;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@Embedded
|
|
||||||
private Position position;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
private int state;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
private int maxStates;
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public class Train {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
private Branch currentBranch;
|
|
||||||
}
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package nl.andrewl.railsignalapi.model.component;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import nl.andrewl.railsignalapi.model.RailSystem;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a physical component of the rail system that the API can interact
|
||||||
|
* with, and send or receive data from. For example, a signal, switch, or
|
||||||
|
* detector.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
|
@Getter
|
||||||
|
public abstract class Component {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rail system that this component belongs to.
|
||||||
|
*/
|
||||||
|
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||||
|
private RailSystem railSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position of this component in the system.
|
||||||
|
*/
|
||||||
|
@Embedded
|
||||||
|
private Position position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A human-readable name for the component.
|
||||||
|
*/
|
||||||
|
@Column(unique = true)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this component is online, meaning that an in-world device is
|
||||||
|
* currently connected to relay information regarding this component.
|
||||||
|
*/
|
||||||
|
@Column(nullable = false)
|
||||||
|
@Setter
|
||||||
|
private boolean online = false;
|
||||||
|
|
||||||
|
public Component(RailSystem railSystem, Position position, String name) {
|
||||||
|
this.railSystem = railSystem;
|
||||||
|
this.position = position;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
return o instanceof Component c && this.id != null && this.id.equals(c.id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package nl.andrewl.railsignalapi.model.component;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import nl.andrewl.railsignalapi.model.RailSystem;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A node that, together with other nodes, forms a path that trains can follow
|
||||||
|
* to traverse through segments in the rail system.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
|
@Getter
|
||||||
|
public class PathNode extends Component {
|
||||||
|
/**
|
||||||
|
* The set of nodes that this one is connected to.
|
||||||
|
*/
|
||||||
|
@ManyToMany
|
||||||
|
private Set<PathNode> connectedNodes;
|
||||||
|
|
||||||
|
public PathNode(RailSystem railSystem, Position position, String name, Set<PathNode> connectedNodes) {
|
||||||
|
super(railSystem, position, name);
|
||||||
|
this.connectedNodes = connectedNodes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.railsignalapi.model;
|
package nl.andrewl.railsignalapi.model.component;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
@ -6,6 +6,9 @@ import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A three-dimensional position for a component within a system.
|
||||||
|
*/
|
||||||
@Embeddable
|
@Embeddable
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.andrewl.railsignalapi.model.component;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import nl.andrewl.railsignalapi.model.RailSystem;
|
||||||
|
import nl.andrewl.railsignalapi.model.Segment;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component that relays information about trains traversing from one segment
|
||||||
|
* to another. It links exactly two segments together at a specific point.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
|
@Getter
|
||||||
|
public class SegmentBoundaryNode extends PathNode {
|
||||||
|
/**
|
||||||
|
* The set of segments that this boundary node connects. This should
|
||||||
|
* generally always have exactly two segments.
|
||||||
|
*/
|
||||||
|
@ManyToMany
|
||||||
|
private Set<Segment> segments;
|
||||||
|
|
||||||
|
public SegmentBoundaryNode(RailSystem railSystem, Position position, String name, Set<PathNode> connectedNodes, Set<Segment> segments) {
|
||||||
|
super(railSystem, position, name, connectedNodes);
|
||||||
|
this.segments = segments;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package nl.andrewl.railsignalapi.model.component;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import nl.andrewl.railsignalapi.model.Direction;
|
||||||
|
import nl.andrewl.railsignalapi.model.RailSystem;
|
||||||
|
import nl.andrewl.railsignalapi.model.Segment;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A signal is a component that relays the status of a connected segment to
|
||||||
|
* some sort of in-world representation, whether that be a certain light
|
||||||
|
* color, or electrical signal.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
|
public class Signal extends Component {
|
||||||
|
/**
|
||||||
|
* The direction this signal is facing. This is the direction in which the
|
||||||
|
* signal connects to a branch.
|
||||||
|
* <pre>
|
||||||
|
* |-segment A-|-segment B-|
|
||||||
|
* ===================== <- Rail
|
||||||
|
* ]+ ---> Signal is facing East, and shows status on
|
||||||
|
* its western side. It is connected to segment B.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Direction direction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The segment that this signal connects to.
|
||||||
|
*/
|
||||||
|
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||||
|
private Segment segment;
|
||||||
|
|
||||||
|
public Signal(RailSystem railSystem, Position position, String name, Segment segment, Direction direction) {
|
||||||
|
super(railSystem, position, name);
|
||||||
|
this.segment = segment;
|
||||||
|
this.direction = direction;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package nl.andrewl.railsignalapi.model.component;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A switch is a component that directs traffic between several connected
|
||||||
|
* segments.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
|
@Getter
|
||||||
|
public class Switch extends PathNode {
|
||||||
|
/**
|
||||||
|
* The set of all possible configurations that this switch can be in.
|
||||||
|
*/
|
||||||
|
@OneToMany(mappedBy = "switchComponent", orphanRemoval = true, cascade = CascadeType.ALL)
|
||||||
|
private Set<SwitchConfiguration> possibleConfigurations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The switch configuration that this switch is currently in.
|
||||||
|
*/
|
||||||
|
@OneToOne(optional = false, fetch = FetchType.LAZY)
|
||||||
|
private SwitchConfiguration activeConfiguration;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.andrewl.railsignalapi.model.component;
|
||||||
|
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A possible connection that can be made between path nodes, if this is set
|
||||||
|
* as an active configuration in the linked switch component.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class SwitchConfiguration {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The switch component that this configuration belongs to.
|
||||||
|
*/
|
||||||
|
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||||
|
private Switch switchComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of nodes that this switch configuration connects. This should
|
||||||
|
* be almost always a set of two nodes.
|
||||||
|
*/
|
||||||
|
@ManyToMany(fetch = FetchType.EAGER)
|
||||||
|
private Set<PathNode> nodes;
|
||||||
|
}
|
|
@ -1,38 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.rest;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import nl.andrewl.railsignalapi.rest.dto.BranchResponse;
|
|
||||||
import nl.andrewl.railsignalapi.rest.dto.SignalResponse;
|
|
||||||
import nl.andrewl.railsignalapi.service.BranchService;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(path = "/api/railSystems/{rsId}/branches")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class BranchesController {
|
|
||||||
private final BranchService branchService;
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
public List<BranchResponse> getAllBranches(@PathVariable long rsId) {
|
|
||||||
return branchService.getAllBranches(rsId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(path = "/{branchId}")
|
|
||||||
public BranchResponse getBranch(@PathVariable long rsId, @PathVariable long branchId) {
|
|
||||||
return branchService.getBranch(rsId, branchId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(path = "/{branchId}/signals")
|
|
||||||
public List<SignalResponse> getBranchSignals(@PathVariable long rsId, @PathVariable long branchId) {
|
|
||||||
return branchService.getConnectedSignals(rsId, branchId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping(path = "/{branchId}")
|
|
||||||
public ResponseEntity<?> deleteBranch(@PathVariable long rsId, @PathVariable long branchId) {
|
|
||||||
branchService.deleteBranch(rsId, branchId);
|
|
||||||
return ResponseEntity.noContent().build();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(path = "/api/railSystems")
|
@RequestMapping(path = "/api/rs")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class RailSystemsApiController {
|
public class RailSystemsApiController {
|
||||||
private final RailSystemService railSystemService;
|
private final RailSystemService railSystemService;
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.rest;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import nl.andrewl.railsignalapi.rest.dto.SignalConnectionsUpdatePayload;
|
|
||||||
import nl.andrewl.railsignalapi.rest.dto.SignalCreationPayload;
|
|
||||||
import nl.andrewl.railsignalapi.rest.dto.SignalResponse;
|
|
||||||
import nl.andrewl.railsignalapi.service.SignalService;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(path = "/api/railSystems/{rsId}/signals")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class SignalsApiController {
|
|
||||||
private final SignalService signalService;
|
|
||||||
|
|
||||||
@PostMapping
|
|
||||||
public SignalResponse createSignal(@PathVariable long rsId, @RequestBody SignalCreationPayload payload) {
|
|
||||||
return signalService.createSignal(rsId, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
public List<SignalResponse> getSignals(@PathVariable long rsId) {
|
|
||||||
return signalService.getAllSignals(rsId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(path = "/{sigId}")
|
|
||||||
public SignalResponse getSignal(@PathVariable long rsId, @PathVariable long sigId) {
|
|
||||||
return signalService.getSignal(rsId, sigId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(path = "/{sigId}/signalConnections")
|
|
||||||
public SignalResponse updateSignalConnections(@PathVariable long rsId, @PathVariable long sigId, @RequestBody SignalConnectionsUpdatePayload payload) {
|
|
||||||
return signalService.updateSignalBranchConnections(rsId, sigId, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping(path = "/{sigId}")
|
|
||||||
public ResponseEntity<?> deleteSignal(@PathVariable long rsId, @PathVariable long sigId) {
|
|
||||||
signalService.deleteSignal(rsId, sigId);
|
|
||||||
return ResponseEntity.noContent().build();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.rest.dto;
|
|
||||||
|
|
||||||
import nl.andrewl.railsignalapi.model.Branch;
|
|
||||||
|
|
||||||
public record BranchResponse(
|
|
||||||
long id,
|
|
||||||
String name,
|
|
||||||
String status
|
|
||||||
) {
|
|
||||||
public BranchResponse(Branch branch) {
|
|
||||||
this(branch.getId(), branch.getName(), branch.getStatus().name());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.rest.dto;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public record SignalConnectionsUpdatePayload(
|
|
||||||
List<ConnectionData> connections
|
|
||||||
) {
|
|
||||||
public static record ConnectionData(long from, long to) {}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.rest.dto;
|
|
||||||
|
|
||||||
import nl.andrewl.railsignalapi.model.Position;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public record SignalCreationPayload(
|
|
||||||
String name,
|
|
||||||
Position position,
|
|
||||||
List<BranchData> branchConnections
|
|
||||||
) {
|
|
||||||
public static record BranchData(String direction, String name, Long id) {}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
package nl.andrewl.railsignalapi.rest.dto;
|
|
||||||
|
|
||||||
import nl.andrewl.railsignalapi.model.Position;
|
|
||||||
import nl.andrewl.railsignalapi.model.Signal;
|
|
||||||
import nl.andrewl.railsignalapi.model.SignalBranchConnection;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public record SignalResponse(
|
|
||||||
long id,
|
|
||||||
String name,
|
|
||||||
Position position,
|
|
||||||
List<ConnectionData> branchConnections,
|
|
||||||
boolean online
|
|
||||||
) {
|
|
||||||
public SignalResponse(Signal signal) {
|
|
||||||
this(
|
|
||||||
signal.getId(),
|
|
||||||
signal.getName(),
|
|
||||||
signal.getPosition(),
|
|
||||||
signal.getBranchConnections().stream()
|
|
||||||
.sorted(Comparator.comparing(SignalBranchConnection::getDirection))
|
|
||||||
.map(ConnectionData::new)
|
|
||||||
.toList(),
|
|
||||||
signal.isOnline()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static record ConnectionData(
|
|
||||||
long id,
|
|
||||||
String direction,
|
|
||||||
BranchResponse branch,
|
|
||||||
List<ReachableConnectionData> reachableSignalConnections
|
|
||||||
) {
|
|
||||||
public ConnectionData(SignalBranchConnection c) {
|
|
||||||
this(
|
|
||||||
c.getId(),
|
|
||||||
c.getDirection().name(),
|
|
||||||
new BranchResponse(c.getBranch()),
|
|
||||||
c.getReachableSignalConnections().stream()
|
|
||||||
.map(cc -> new ReachableConnectionData(
|
|
||||||
cc.getId(),
|
|
||||||
cc.getDirection().name(),
|
|
||||||
cc.getSignal().getId(),
|
|
||||||
cc.getSignal().getName(),
|
|
||||||
cc.getSignal().getPosition()
|
|
||||||
))
|
|
||||||
.toList()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static record ReachableConnectionData(
|
|
||||||
long connectionId,
|
|
||||||
String direction,
|
|
||||||
long signalId,
|
|
||||||
String signalName,
|
|
||||||
Position signalPosition
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,9 @@
|
||||||
package nl.andrewl.railsignalapi.service;
|
package nl.andrewl.railsignalapi.service;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import nl.andrewl.railsignalapi.dao.BranchRepository;
|
import nl.andrewl.railsignalapi.dao.ComponentRepository;
|
||||||
import nl.andrewl.railsignalapi.dao.RailSystemRepository;
|
import nl.andrewl.railsignalapi.dao.RailSystemRepository;
|
||||||
import nl.andrewl.railsignalapi.dao.SignalRepository;
|
import nl.andrewl.railsignalapi.dao.SegmentRepository;
|
||||||
import nl.andrewl.railsignalapi.model.RailSystem;
|
import nl.andrewl.railsignalapi.model.RailSystem;
|
||||||
import nl.andrewl.railsignalapi.rest.dto.RailSystemCreationPayload;
|
import nl.andrewl.railsignalapi.rest.dto.RailSystemCreationPayload;
|
||||||
import nl.andrewl.railsignalapi.rest.dto.RailSystemResponse;
|
import nl.andrewl.railsignalapi.rest.dto.RailSystemResponse;
|
||||||
|
@ -19,8 +19,8 @@ import java.util.List;
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class RailSystemService {
|
public class RailSystemService {
|
||||||
private final RailSystemRepository railSystemRepository;
|
private final RailSystemRepository railSystemRepository;
|
||||||
private final SignalRepository signalRepository;
|
private final SegmentRepository segmentRepository;
|
||||||
private final BranchRepository branchRepository;
|
private final ComponentRepository componentRepository;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public List<RailSystemResponse> getRailSystems() {
|
public List<RailSystemResponse> getRailSystems() {
|
||||||
|
@ -40,10 +40,8 @@ public class RailSystemService {
|
||||||
public void delete(long rsId) {
|
public void delete(long rsId) {
|
||||||
var rs = railSystemRepository.findById(rsId)
|
var rs = railSystemRepository.findById(rsId)
|
||||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
var signals = signalRepository.findAllByRailSystemOrderByName(rs);
|
componentRepository.deleteAllByRailSystem(rs);
|
||||||
signalRepository.deleteAll(signals);
|
segmentRepository.deleteAllByRailSystem(rs);
|
||||||
var branches = branchRepository.findAllByRailSystemOrderByName(rs);
|
|
||||||
branchRepository.deleteAll(branches);
|
|
||||||
railSystemRepository.delete(rs);
|
railSystemRepository.delete(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import nl.andrewl.railsignalapi.dao.RailSystemRepository;
|
||||||
import nl.andrewl.railsignalapi.dao.SignalBranchConnectionRepository;
|
import nl.andrewl.railsignalapi.dao.SignalBranchConnectionRepository;
|
||||||
import nl.andrewl.railsignalapi.dao.SignalRepository;
|
import nl.andrewl.railsignalapi.dao.SignalRepository;
|
||||||
import nl.andrewl.railsignalapi.model.*;
|
import nl.andrewl.railsignalapi.model.*;
|
||||||
|
import nl.andrewl.railsignalapi.model.component.SignalBranchConnection;
|
||||||
import nl.andrewl.railsignalapi.rest.dto.SignalConnectionsUpdatePayload;
|
import nl.andrewl.railsignalapi.rest.dto.SignalConnectionsUpdatePayload;
|
||||||
import nl.andrewl.railsignalapi.rest.dto.SignalCreationPayload;
|
import nl.andrewl.railsignalapi.rest.dto.SignalCreationPayload;
|
||||||
import nl.andrewl.railsignalapi.rest.dto.SignalResponse;
|
import nl.andrewl.railsignalapi.rest.dto.SignalResponse;
|
||||||
|
|
Loading…
Reference in New Issue