|
@@ -1,21 +1,25 @@
|
|
|
-// package elem_link -- связь между объектами
|
|
|
|
|
-package elem_link
|
|
|
|
|
|
|
+// package arch_link -- связь между архитектурными объектами
|
|
|
|
|
+package arch_link
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
"fmt"
|
|
"fmt"
|
|
|
|
|
|
|
|
"gitp78su.ipnodns.ru/svi/kern/v3"
|
|
"gitp78su.ipnodns.ru/svi/kern/v3"
|
|
|
|
|
+ "gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
|
|
|
|
|
|
|
|
|
|
+ "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
|
|
|
"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
|
|
"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
|
|
|
"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
|
|
"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
|
|
|
|
|
+ "gitp78su.ipnodns.ru/svi/goarch/lev1/arch_text"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-// ElemLink -- связь между объектами
|
|
|
|
|
-type ElemLink struct {
|
|
|
|
|
- types.IViewLabel
|
|
|
|
|
- CoordEnd_ types.IViewCoord `yaml:"coord_end"` // Координаты второй точки
|
|
|
|
|
- Src_ types.IElemBase `yaml:"src"` // Источник координат
|
|
|
|
|
- Dst_ types.IElemBase `yaml:"dst"` // Получатель координат
|
|
|
|
|
|
|
+// ArchLink -- связь между архитектурными объектами
|
|
|
|
|
+type ArchLink struct {
|
|
|
|
|
+ *arch_text.ArchText
|
|
|
|
|
+ SrcId_ alias.ArchId `yaml:"src_id"` // Источник координат
|
|
|
|
|
+ src types.IArchNode
|
|
|
|
|
+ DstId_ alias.ArchId `yaml:"dst_id"` // Получатель координат
|
|
|
|
|
+ dst types.IArchNode
|
|
|
|
|
|
|
|
TypeLink_ string `yaml:"type_link"` // Тип связи
|
|
TypeLink_ string `yaml:"type_link"` // Тип связи
|
|
|
}
|
|
}
|
|
@@ -24,54 +28,54 @@ var (
|
|
|
hassert = kern.GetFnHassert()
|
|
hassert = kern.GetFnHassert()
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-// NewElemLink -- возвращает новую связь
|
|
|
|
|
-func NewElemLink(elemLabel types.IViewLabel, coordEnd types.IViewCoord,
|
|
|
|
|
- src, dst types.IElemBase, typeLink string) types.IElemLink {
|
|
|
|
|
-
|
|
|
|
|
- sf := &ElemLink{
|
|
|
|
|
- IViewLabel: elemLabel,
|
|
|
|
|
- CoordEnd_: coordEnd,
|
|
|
|
|
- Src_: src,
|
|
|
|
|
- Dst_: dst,
|
|
|
|
|
- TypeLink_: typeLink,
|
|
|
|
|
|
|
+// NewArchLink -- возвращает новую связь
|
|
|
|
|
+func NewArchLink(archText *arch_text.ArchText) *ArchLink {
|
|
|
|
|
+ hassert(archText != nil, "NewArchLink: archText == nil")
|
|
|
|
|
+ sf := &ArchLink{
|
|
|
|
|
+ ArchText: archText,
|
|
|
}
|
|
}
|
|
|
- sf.SelfCheck()
|
|
|
|
|
|
|
+ _ = types.IArchLink(sf)
|
|
|
return sf
|
|
return sf
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// SelfCheck -- самопроверка элемента
|
|
|
|
|
-func (sf *ElemLink) SelfCheck() {
|
|
|
|
|
- sf.IViewLabel.SelfCheck()
|
|
|
|
|
- hassert(sf.CoordEnd_ != nil, "ElemLink.SelfCheck(): id=%v, CoordEnd_ == nil", sf.Id())
|
|
|
|
|
- hassert(sf.Src_ != nil, "ElemLink.SelfCheck(): id=%v, Src_ == nil", sf.Id())
|
|
|
|
|
- hassert(sf.Dst_ != nil, "ElemLink.SelfCheck(): id=%v, Dst_ == nil", sf.Id())
|
|
|
|
|
- hassert(sf.TypeLink_ != "", "ElemLink.SelfCheck(): id=%v, TypeLink_ is empty", sf.Id())
|
|
|
|
|
|
|
+// InvarCheck -- самопроверка элемента
|
|
|
|
|
+func (sf *ArchLink) InvarCheck() ktypes.Option[error] {
|
|
|
|
|
+ optErr := sf.InvarNode()
|
|
|
|
|
+ if optErr.IsVal() {
|
|
|
|
|
+ return optErr
|
|
|
|
|
+ }
|
|
|
|
|
+ if sf.SrcId_ == "" {
|
|
|
|
|
+ err := fmt.Errorf("ArchLink.SelfCheck(): id=%v, Src_ == nil", sf.Id())
|
|
|
|
|
+ return ktypes.NewSome(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if sf.DstId_ == "" {
|
|
|
|
|
+ err := fmt.Errorf("ArchLink.SelfCheck(): id=%v, Dst_ == nil", sf.Id())
|
|
|
|
|
+ return ktypes.NewSome(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if sf.TypeLink_ == "" {
|
|
|
|
|
+ err := fmt.Errorf("ArchLink.SelfCheck(): id=%v, TypeLink_ is empty", sf.Id())
|
|
|
|
|
+ return ktypes.NewSome(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ return ktypes.NewNone[error]()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// TypeLink -- тип связи
|
|
// TypeLink -- тип связи
|
|
|
//
|
|
//
|
|
|
//go:fix inline
|
|
//go:fix inline
|
|
|
-func (sf *ElemLink) TypeLink() string {
|
|
|
|
|
|
|
+func (sf *ArchLink) TypeLink() string {
|
|
|
return sf.TypeLink_
|
|
return sf.TypeLink_
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// CoordEnd -- координаты конца связи
|
|
|
|
|
-//
|
|
|
|
|
-//go:fix inline
|
|
|
|
|
-func (sf *ElemLink) CoordEnd() types.IViewCoord {
|
|
|
|
|
- return sf.CoordEnd_
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
// Links -- ссылки актора
|
|
// Links -- ссылки актора
|
|
|
-func (sf *ElemLink) Links() []types.IElemBase {
|
|
|
|
|
- return []types.IElemBase{sf.Src_, sf.Dst_}
|
|
|
|
|
|
|
+func (sf *ArchLink) Links() []types.IArchNode {
|
|
|
|
|
+ return []types.IArchNode{sf.src, sf.dst}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Check -- проверяет связи между объектами
|
|
// Check -- проверяет связи между объектами
|
|
|
-func (sf *ElemLink) Check() string {
|
|
|
|
|
- if sf.Dst_.Id() == sf.Src_.Id() {
|
|
|
|
|
|
|
+func (sf *ArchLink) Check() string {
|
|
|
|
|
+ if sf.DstId_ == sf.SrcId_ {
|
|
|
return fmt.Sprintf("ВНИМАНИЕ! Источник и получатель совпадают\nsrc=%v, dst=%v\n",
|
|
return fmt.Sprintf("ВНИМАНИЕ! Источник и получатель совпадают\nsrc=%v, dst=%v\n",
|
|
|
- sf.Src_.Id(), sf.Dst_.Id())
|
|
|
|
|
|
|
+ sf.SrcId_, sf.DstId_)
|
|
|
}
|
|
}
|
|
|
if msgErr := sf.checkSrc(); msgErr != "" {
|
|
if msgErr := sf.checkSrc(); msgErr != "" {
|
|
|
return "ОШИБКА при проверке связи источника\n" + msgErr
|
|
return "ОШИБКА при проверке связи источника\n" + msgErr
|
|
@@ -86,16 +90,17 @@ func (sf *ElemLink) Check() string {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// проверить связь получателя
|
|
// проверить связь получателя
|
|
|
-func (sf *ElemLink) checkDst() string {
|
|
|
|
|
- if sf.Dst_ == nil {
|
|
|
|
|
|
|
+func (sf *ArchLink) checkDst() string {
|
|
|
|
|
+ if sf.DstId_ == "" {
|
|
|
return "ОШИБКА получатель `dst` не задан"
|
|
return "ОШИБКА получатель `dst` не задан"
|
|
|
}
|
|
}
|
|
|
// Вычислить на допустимые типы для получателя
|
|
// Вычислить на допустимые типы для получателя
|
|
|
- switch sf.Dst_.Type() {
|
|
|
|
|
|
|
+ switch sf.dst.Type() {
|
|
|
case cons.TypeUseActor:
|
|
case cons.TypeUseActor:
|
|
|
- actor, isOk := sf.Dst_.(types.IElemActor)
|
|
|
|
|
|
|
+ actor, isOk := sf.dst.(types.IArchActor)
|
|
|
if !isOk {
|
|
if !isOk {
|
|
|
- return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n", sf.Dst_.Id(), sf.Dst_.Type())
|
|
|
|
|
|
|
+ return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n",
|
|
|
|
|
+ sf.DstId_, sf.dst.Type())
|
|
|
}
|
|
}
|
|
|
isOk = false
|
|
isOk = false
|
|
|
for _, id := range actor.GroupLink().Links() {
|
|
for _, id := range actor.GroupLink().Links() {
|
|
@@ -109,20 +114,20 @@ func (sf *ElemLink) checkDst() string {
|
|
|
sf.Id(), actor.Id())
|
|
sf.Id(), actor.Id())
|
|
|
}
|
|
}
|
|
|
case cons.TypeUseLink:
|
|
case cons.TypeUseLink:
|
|
|
- link, isOk := sf.Dst_.(types.IElemLink)
|
|
|
|
|
|
|
+ link, isOk := sf.dst.(types.IArchLink)
|
|
|
if !isOk {
|
|
if !isOk {
|
|
|
return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n",
|
|
return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n",
|
|
|
- sf.Dst_.Id(), sf.Dst_.Type())
|
|
|
|
|
|
|
+ sf.DstId_, sf.dst.Type())
|
|
|
}
|
|
}
|
|
|
- isOk = sf.Id() == link.Dst().Id() || sf.Id() == link.Src().Id()
|
|
|
|
|
|
|
+ isOk = sf.Id() == link.DstId() || sf.Id() == link.SrcId()
|
|
|
if !isOk {
|
|
if !isOk {
|
|
|
return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.Id(), link.Id())
|
|
return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.Id(), link.Id())
|
|
|
}
|
|
}
|
|
|
case cons.TypeUseCase:
|
|
case cons.TypeUseCase:
|
|
|
- useCase, isOk := sf.Dst_.(types.IElemUseCase)
|
|
|
|
|
|
|
+ useCase, isOk := sf.dst.(types.IArchUseCase)
|
|
|
if !isOk {
|
|
if !isOk {
|
|
|
return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nтип=%q\n",
|
|
return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nтип=%q\n",
|
|
|
- sf.Id(), sf.Dst_.Id(), sf.Dst_.Type())
|
|
|
|
|
|
|
+ sf.Id(), sf.DstId_, sf.dst.Type())
|
|
|
}
|
|
}
|
|
|
isOk = false
|
|
isOk = false
|
|
|
for id := range useCase.Links() {
|
|
for id := range useCase.Links() {
|
|
@@ -137,20 +142,20 @@ func (sf *ElemLink) checkDst() string {
|
|
|
}
|
|
}
|
|
|
default: // Недопустимый источник
|
|
default: // Недопустимый источник
|
|
|
return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nid=%q\n",
|
|
return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nid=%q\n",
|
|
|
- sf.Id(), sf.Dst_.Type(), sf.Dst_.Id())
|
|
|
|
|
|
|
+ sf.Id(), sf.dst.Type(), sf.DstId_)
|
|
|
}
|
|
}
|
|
|
return ""
|
|
return ""
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Проверяет связь источника
|
|
// Проверяет связь источника
|
|
|
-func (sf *ElemLink) checkSrc() string {
|
|
|
|
|
- if sf.Src_ == nil {
|
|
|
|
|
|
|
+func (sf *ArchLink) checkSrc() string {
|
|
|
|
|
+ if sf.src == nil {
|
|
|
return "ВНИМАНИЕ! Источник связи не задан(src)\n"
|
|
return "ВНИМАНИЕ! Источник связи не задан(src)\n"
|
|
|
}
|
|
}
|
|
|
- switch sf.Src_.Type() {
|
|
|
|
|
|
|
+ switch sf.src.Type() {
|
|
|
case cons.TypeUseActor:
|
|
case cons.TypeUseActor:
|
|
|
isOk := false
|
|
isOk := false
|
|
|
- actor := sf.Src_.(types.IElemActor)
|
|
|
|
|
|
|
+ actor := sf.src.(types.IArchActor)
|
|
|
for _, id := range actor.GroupLink().Links() { // Проверка на взаимность
|
|
for _, id := range actor.GroupLink().Links() { // Проверка на взаимность
|
|
|
if id == sf.Id() {
|
|
if id == sf.Id() {
|
|
|
isOk = true
|
|
isOk = true
|
|
@@ -161,21 +166,21 @@ func (sf *ElemLink) checkSrc() string {
|
|
|
return fmt.Sprintf("Невзаимная ссылка с актором %q\n", actor.Id())
|
|
return fmt.Sprintf("Невзаимная ссылка с актором %q\n", actor.Id())
|
|
|
}
|
|
}
|
|
|
case cons.TypeUseLink:
|
|
case cons.TypeUseLink:
|
|
|
- link, isOk := sf.Src_.(types.IElemLink)
|
|
|
|
|
|
|
+ link, isOk := sf.src.(types.IArchLink)
|
|
|
if !isOk {
|
|
if !isOk {
|
|
|
return fmt.Sprintf("Несоответствие типа источника(%q)\nтип='useLink'\n",
|
|
return fmt.Sprintf("Несоответствие типа источника(%q)\nтип='useLink'\n",
|
|
|
- sf.Src_.Id())
|
|
|
|
|
|
|
+ sf.SrcId_)
|
|
|
}
|
|
}
|
|
|
- isOk = sf.Id() == link.Dst().Id() || sf.Id() == link.Src().Id()
|
|
|
|
|
|
|
+ isOk = sf.Id() == link.DstId() || sf.Id() == link.SrcId()
|
|
|
if !isOk {
|
|
if !isOk {
|
|
|
return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n",
|
|
return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n",
|
|
|
sf.Id(), link.Id())
|
|
sf.Id(), link.Id())
|
|
|
}
|
|
}
|
|
|
case cons.TypeUseCase:
|
|
case cons.TypeUseCase:
|
|
|
- useCase, isOk := sf.Src_.(types.IElemUseCase)
|
|
|
|
|
|
|
+ useCase, isOk := sf.src.(types.IArchUseCase)
|
|
|
if !isOk {
|
|
if !isOk {
|
|
|
return fmt.Sprintf("id=%q, Тип источника(%q) не совпадает с фактическим\nтип='useCase'\n",
|
|
return fmt.Sprintf("id=%q, Тип источника(%q) не совпадает с фактическим\nтип='useCase'\n",
|
|
|
- sf.Id(), sf.Src_.Id())
|
|
|
|
|
|
|
+ sf.Id(), sf.SrcId())
|
|
|
}
|
|
}
|
|
|
isOk = false
|
|
isOk = false
|
|
|
for id := range useCase.Links() { // Проверка на взаимность
|
|
for id := range useCase.Links() { // Проверка на взаимность
|
|
@@ -190,21 +195,21 @@ func (sf *ElemLink) checkSrc() string {
|
|
|
}
|
|
}
|
|
|
default: // Неизвестный источник
|
|
default: // Неизвестный источник
|
|
|
return fmt.Sprintf("id=%q, неизвестный тип источника(%q)<br>id=%q\n",
|
|
return fmt.Sprintf("id=%q, неизвестный тип источника(%q)<br>id=%q\n",
|
|
|
- sf.Id(), sf.Src_.Type(), sf.Src_.Id())
|
|
|
|
|
|
|
+ sf.Id(), sf.src.Type(), sf.SrcId())
|
|
|
}
|
|
}
|
|
|
return ""
|
|
return ""
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Src -- возвращает источник связи
|
|
|
|
|
|
|
+// SrcId -- возвращает ID источника связи
|
|
|
//
|
|
//
|
|
|
//go:fix inline
|
|
//go:fix inline
|
|
|
-func (sf *ElemLink) Src() types.IElemBase {
|
|
|
|
|
- return sf.Src_
|
|
|
|
|
|
|
+func (sf *ArchLink) SrcId() alias.ArchId {
|
|
|
|
|
+ return sf.SrcId_
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Dst -- возвращает получателя связи
|
|
|
|
|
|
|
+// DstId -- возвращает ID получателя связи
|
|
|
//
|
|
//
|
|
|
//go:fix inline
|
|
//go:fix inline
|
|
|
-func (sf *ElemLink) Dst() types.IElemBase {
|
|
|
|
|
- return sf.Dst_
|
|
|
|
|
|
|
+func (sf *ArchLink) DstId() alias.ArchId {
|
|
|
|
|
+ return sf.DstId_
|
|
|
}
|
|
}
|