| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- // package elem_link -- связь между объектами
- package elem_link
- import (
- "fmt"
- "gitp78su.ipnodns.ru/svi/kern/v3"
- "gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
- "gitp78su.ipnodns.ru/svi/goarch/lev0/types"
- )
- // ElemLink -- связь между объектами
- type ElemLink struct {
- types.IElemBase
- CoordEnd_ types.ICoord `yaml:"coord_end"` // Координаты второй точки
- Src_ types.IElemBase `yaml:"src"` // Источник координат
- Dst_ types.IElemBase `yaml:"dst"` // Получатель координат
- TypeLink_ string `yaml:"typeLink"` // Тип связи
- }
- var (
- hassert = kern.GetFnHassert()
- )
- // NewElemLink -- возвращает новую связь
- func NewElemLink(elemBase types.IElemBase, coordEnd types.ICoord,
- src, dst types.IElemBase, typeLink string) types.IElemLink {
- sf := &ElemLink{
- IElemBase: elemBase,
- CoordEnd_: coordEnd,
- Src_: src,
- Dst_: dst,
- TypeLink_: typeLink,
- }
- return sf
- }
- // SelfCheck -- самопроверка элемента
- func (sf *ElemLink) SelfCheck() {
- sf.IElemBase.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())
- }
- // CoordEnd -- координаты конца связи
- //
- //go:fix inline
- func (sf *ElemLink) CoordEnd() types.ICoord {
- return sf.CoordEnd_
- }
- // Links -- ссылки актора
- func (sf *ElemLink) Links() []types.IElemBase {
- return []types.IElemBase{sf.Src_, sf.Dst_}
- }
- // Check -- проверяет связи между объектами
- func (sf *ElemLink) Check() string {
- if sf.Dst_.Id() == sf.Src_.Id() {
- return fmt.Sprintf("ВНИМАНИЕ! Источник и получатель совпадают\nsrc=%v, dst=%v\n",
- sf.Src_.Id(), sf.Dst_.Id())
- }
- if msgErr := sf.checkSrc(); msgErr != "" {
- return "ОШИБКА при проверке связи источника\n" + msgErr
- }
- if msgErr := sf.checkDst(); msgErr != "" {
- return "ОШИБКА при проверке связи получателя\n" + msgErr
- }
- if sf.TypeLink_ == "" { // Проверка на правильность типа связи
- return "Пустой собственный тип связи\n"
- }
- return ""
- }
- // проверить связь получателя
- func (sf *ElemLink) checkDst() string {
- if sf.Dst_ == nil {
- return "ОШИБКА получатель `dst` не задан"
- }
- // Вычислить на допустимые типы для получателя
- switch sf.Dst_.Type() {
- case cons.TypeUseActor:
- actor, isOk := sf.Dst_.(types.IActor)
- if !isOk {
- return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n", sf.Dst_.Id(), sf.Dst_.Type())
- }
- isOk = false
- for _, id := range actor.Links() {
- if id == sf.Id() {
- isOk = true
- break
- }
- }
- if !isOk {
- return fmt.Sprintf("Невзаимная ссылка\nid=%q,dst=(%q)",
- sf.Id(), actor.Id())
- }
- case cons.TypeUseLink:
- link, isOk := sf.Dst_.(types.IElemLink)
- if !isOk {
- return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n",
- sf.Dst_.Id(), sf.Dst_.Type())
- }
- isOk = sf.Id() == link.Dst().Id() || sf.Id() == link.Src().Id()
- if !isOk {
- return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.Id(), link.Id())
- }
- case cons.TypeUseCase:
- useCase, isOk := sf.Dst_.(types.IElemUseCase)
- if !isOk {
- return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nтип=%q\n",
- sf.Id(), sf.Dst_.Id(), sf.Dst_.Type())
- }
- isOk = false
- for id := range useCase.Links() {
- if id == sf.Id() {
- isOk = true
- break
- }
- }
- if !isOk {
- return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n",
- sf.Id(), useCase.Id())
- }
- default: // Недопустимый источник
- return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nid=%q\n",
- sf.Id(), sf.Dst_.Type(), sf.Dst_.Id())
- }
- return ""
- }
- // Проверяет связь источника
- func (sf *ElemLink) checkSrc() string {
- if sf.Src_ == nil {
- return "ВНИМАНИЕ! Источник связи не задан(src)\n"
- }
- switch sf.Src_.Type() {
- case cons.TypeUseActor:
- isOk := false
- actor := sf.Src_.(types.IActor)
- for _, id := range actor.Links() { // Проверка на взаимность
- if id == sf.Id() {
- isOk = true
- break
- }
- }
- if !isOk {
- return fmt.Sprintf("Невзаимная ссылка с актором %q\n", actor.Id())
- }
- case cons.TypeUseLink:
- link, isOk := sf.Src_.(types.IElemLink)
- if !isOk {
- return fmt.Sprintf("Несоответствие типа источника(%q)\nтип='useLink'\n",
- sf.Src_.Id())
- }
- isOk = sf.Id() == link.Dst().Id() || sf.Id() == link.Src().Id()
- if !isOk {
- return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n",
- sf.Id(), link.Id())
- }
- case cons.TypeUseCase:
- useCase, isOk := sf.Src_.(types.IElemUseCase)
- if !isOk {
- return fmt.Sprintf("id=%q, Тип источника(%q) не совпадает с фактическим\nтип='useCase'\n",
- sf.Id(), sf.Src_.Id())
- }
- isOk = false
- for id := range useCase.Links() { // Проверка на взаимность
- if id == sf.Id() {
- isOk = true
- break
- }
- }
- if !isOk {
- return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n",
- sf.Id(), useCase.Id())
- }
- default: // Неизвестный источник
- return fmt.Sprintf("id=%q, неизвестный тип источника(%q)<br>id=%q\n",
- sf.Id(), sf.Src_.Type(), sf.Src_.Id())
- }
- return ""
- }
- // Src -- возвращает источник связи
- //
- //go:fix inline
- func (sf *ElemLink) Src() types.IElemBase {
- return sf.Src_
- }
- // Dst -- возвращает получателя связи
- //
- //go:fix inline
- func (sf *ElemLink) Dst() types.IElemBase {
- return sf.Dst_
- }
|