233 lines
5.9 KiB
Go
233 lines
5.9 KiB
Go
package model
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
)
|
|
|
|
type RtssModel interface {
|
|
// RtssModel unique id
|
|
Uid() string
|
|
}
|
|
|
|
// 通道端口
|
|
type PipePort = string
|
|
|
|
var (
|
|
// PipePortA 通道端口A
|
|
PipePortA PipePort = "A"
|
|
// PipePortB 通道端口B
|
|
PipePortB PipePort = "B"
|
|
// PipePortC 通道端口C
|
|
PipePortC PipePort = "C"
|
|
)
|
|
|
|
var (
|
|
twoPorts = []PipePort{PipePortA, PipePortB}
|
|
threePorts = []PipePort{PipePortA, PipePortB, PipePortC}
|
|
)
|
|
|
|
// 通道连接关系
|
|
type PipeLink struct {
|
|
// 通道元素
|
|
Pipe PipeElement
|
|
// 端口
|
|
Port PipePort
|
|
}
|
|
|
|
func NewPipeLink(pipe PipeElement, port PipePort) *PipeLink {
|
|
if pipe == nil {
|
|
panic("pipe is nil")
|
|
}
|
|
return &PipeLink{
|
|
Pipe: pipe,
|
|
Port: port,
|
|
}
|
|
}
|
|
|
|
func (pl *PipeLink) Debug() string {
|
|
return DebugPipeLink(pl.Pipe, pl.Port)
|
|
}
|
|
|
|
func DebugPipeLink(p PipeElement, port PipePort) string {
|
|
return fmt.Sprintf("{pipeUid=%s, port=%s}", p.Uid(), port)
|
|
}
|
|
|
|
// 通道元素
|
|
type PipeElement interface {
|
|
RtssModel
|
|
// 获取通道端口
|
|
Ports() []PipePort
|
|
IsTwoPorts() bool
|
|
IsThreePorts() bool
|
|
// 获取指定端口连接的通道连接关系
|
|
GetLinkedElement(port PipePort) *PipeLink
|
|
// 设置指定端口的通道连接关系
|
|
SetLinkedElement(port PipePort, pipeLink *PipeLink) error
|
|
// 检查通道连接关系
|
|
CheckPipeLink() error
|
|
}
|
|
|
|
type TwoPortsPipeElement interface {
|
|
PipeElement
|
|
// 获取指定端口的对端通道连接关系
|
|
OppositePipeLink(port PipePort) *PipeLink
|
|
}
|
|
|
|
type ThreePortsPipeElement interface {
|
|
PipeElement
|
|
}
|
|
|
|
func checkPipePortLink(pe PipeElement, port PipePort, pipeLink *PipeLink) error {
|
|
if pipeLink == nil {
|
|
slog.Debug("检查通道端口连接关系", "通道端口", DebugPipeLink(pe, port), "连接关系", "未连接")
|
|
return nil
|
|
}
|
|
slog.Debug("检查通道端口连接关系", "通道端口", DebugPipeLink(pe, port), "连接关系", pipeLink.Debug())
|
|
plink := pipeLink.Pipe.GetLinkedElement(pipeLink.Port)
|
|
if plink == nil {
|
|
return fmt.Errorf("通道端口{uid=%s, port=%s}关联通道端口{uid=%s, port=%s},但关联通道的对应端口却未关联通道端口", pe.Uid(), port, pipeLink.Pipe.Uid(), pipeLink.Port)
|
|
} else if plink.Pipe.Uid() != pe.Uid() || plink.Port != port {
|
|
return fmt.Errorf("通道端口{uid=%s, port=%s}关联通道端口{uid=%s, port=%s},但关联通道的对应端口却关联了其他通道端口: {uid=%s, port=%s}", pe.Uid(), port, pipeLink.Pipe.Uid(), pipeLink.Port,
|
|
plink.Pipe.Uid(), plink.Port)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var _ TwoPortsPipeElement = (*TwoPortsPipeElementImpl)(nil)
|
|
|
|
// 两端口的线性通道元素
|
|
type TwoPortsPipeElementImpl struct {
|
|
uid string
|
|
paPipeLink *PipeLink
|
|
pbPipeLink *PipeLink
|
|
}
|
|
|
|
func (t *TwoPortsPipeElementImpl) Uid() string {
|
|
return t.uid
|
|
}
|
|
|
|
func (t *TwoPortsPipeElementImpl) Ports() []PipePort {
|
|
return twoPorts
|
|
}
|
|
|
|
func (t *TwoPortsPipeElementImpl) IsTwoPorts() bool {
|
|
return true
|
|
}
|
|
|
|
func (t *TwoPortsPipeElementImpl) IsThreePorts() bool {
|
|
return false
|
|
}
|
|
|
|
func (s *TwoPortsPipeElementImpl) GetLinkedElement(port PipePort) *PipeLink {
|
|
if port == PipePortA {
|
|
return s.paPipeLink
|
|
} else if port == PipePortB {
|
|
return s.pbPipeLink
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (t *TwoPortsPipeElementImpl) OppositePipeLink(port PipePort) *PipeLink {
|
|
if port == PipePortA {
|
|
return t.pbPipeLink
|
|
}
|
|
return t.paPipeLink
|
|
}
|
|
|
|
func (s *TwoPortsPipeElementImpl) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
|
|
if port == PipePortA {
|
|
if s.paPipeLink != nil {
|
|
return fmt.Errorf("区段uid=%s端口A已经设置关联元素: {uid=%s, port=%s}", s.uid, s.paPipeLink.Pipe.Uid(), s.paPipeLink.Port)
|
|
}
|
|
s.paPipeLink = pipeLink
|
|
} else if port == PipePortB {
|
|
if s.pbPipeLink != nil {
|
|
return fmt.Errorf("区段uid=%s端口B已经设置关联元素: {uid=%s, port=%s}", s.uid, s.pbPipeLink.Pipe.Uid(), s.pbPipeLink.Port)
|
|
}
|
|
s.pbPipeLink = pipeLink
|
|
} else {
|
|
return fmt.Errorf("区段uid=%s设置关联元素端口错误,不支持C端口", s.uid)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *TwoPortsPipeElementImpl) CheckPipeLink() error {
|
|
err := checkPipePortLink(s, PipePortA, s.paPipeLink)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = checkPipePortLink(s, PipePortB, s.pbPipeLink)
|
|
return err
|
|
}
|
|
|
|
var _ PipeElement = (*ThreePortsPipeElementImpl)(nil)
|
|
|
|
// 三端口的通道元素
|
|
type ThreePortsPipeElementImpl struct {
|
|
uid string
|
|
paPipeLink *PipeLink
|
|
pbPipeLink *PipeLink
|
|
pcPipeLink *PipeLink
|
|
}
|
|
|
|
func (t *ThreePortsPipeElementImpl) Uid() string {
|
|
return t.uid
|
|
}
|
|
|
|
func (t *ThreePortsPipeElementImpl) Ports() []PipePort {
|
|
return threePorts
|
|
}
|
|
|
|
func (t *ThreePortsPipeElementImpl) IsTwoPorts() bool {
|
|
return false
|
|
}
|
|
|
|
func (t *ThreePortsPipeElementImpl) IsThreePorts() bool {
|
|
return true
|
|
}
|
|
|
|
func (t *ThreePortsPipeElementImpl) GetLinkedElement(port PipePort) *PipeLink {
|
|
if port == PipePortA {
|
|
return t.paPipeLink
|
|
} else if port == PipePortB {
|
|
return t.pbPipeLink
|
|
} else if port == PipePortC {
|
|
return t.pcPipeLink
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (t *ThreePortsPipeElementImpl) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
|
|
if port == PipePortA {
|
|
if t.paPipeLink != nil {
|
|
return fmt.Errorf("道岔uid=%s端口A已经设置关联元素: {uid=%s, port=%s}", t.uid, t.paPipeLink.Pipe.Uid(), t.paPipeLink.Port)
|
|
}
|
|
t.paPipeLink = pipeLink
|
|
} else if port == PipePortB {
|
|
if t.pbPipeLink != nil {
|
|
return fmt.Errorf("道岔uid=%s端口B已经设置关联元素: {uid=%s, port=%s}", t.uid, t.pbPipeLink.Pipe.Uid(), t.pbPipeLink.Port)
|
|
}
|
|
t.pbPipeLink = pipeLink
|
|
} else if port == PipePortC {
|
|
if t.pcPipeLink != nil {
|
|
return fmt.Errorf("道岔uid=%s端口C已经设置关联元素: {uid=%s, port=%s}", t.uid, t.pcPipeLink.Pipe.Uid(), t.pcPipeLink.Port)
|
|
}
|
|
t.pcPipeLink = pipeLink
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (t *ThreePortsPipeElementImpl) CheckPipeLink() error {
|
|
err := checkPipePortLink(t, PipePortA, t.paPipeLink)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = checkPipePortLink(t, PipePortB, t.pbPipeLink)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = checkPipePortLink(t, PipePortC, t.pcPipeLink)
|
|
return err
|
|
}
|