// package use_link -- связь между объектами package use_link import ( "fmt" "gitp78su.ipnodns.ru/svi/goarch/lev0/alias" "gitp78su.ipnodns.ru/svi/goarch/lev0/cons" "gitp78su.ipnodns.ru/svi/goarch/lev0/types" "gitp78su.ipnodns.ru/svi/goarch/lev1/coord" "gitp78su.ipnodns.ru/svi/goarch/pkg/elems/elem_base" "gitp78su.ipnodns.ru/svi/kern/v3" ) // UseLink -- связь между объектами type UseLink struct { ElemBase_ *elem_base.ElemBase `yaml:"elem_base"` CoordEnd_ *coord.Coord `yaml:"coord1"` // Координаты второй точки Src_ alias.Id `yaml:"src"` // Источник координат Dst_ alias.Id `yaml:"dst"` // Получатель координат TypeLink_ string `yaml:"typeLink"` // Тип связи } var ( hassert = kern.GetFnHassert() ) // NewUseLink -- возвращает новую связь func NewUseLink(elemBase *elem_base.ElemBase, coordEnd *coord.Coord) *UseLink { hassert(elemBase != nil, "NewUseLink(): elemBase is nil") hassert(coordEnd != nil, "NewUseLink(): coordEnd is nil") id := elemBase.Id_ _src := elemBase.Elem_["src"] src0, isOk := _src.(string) hassert(isOk, "NewUseLink(): id=%q, field `src` not string, type=%T, value=%v", id, _src, elemBase.StrElem_) src := alias.Id(src0) hassert(src != "", "NewUseLink(): id=%q, `src` is empty", id) _dst := elemBase.Elem_["dst"] dst0, isOk := _dst.(string) hassert(isOk, "NewUseLink(): id=%q, field `dst` not string, type=%T, value=%+v
%+v", id, _dst, _dst, elemBase.StrElem_) dst := alias.Id(dst0) _typeLink, isOk := elemBase.Elem_["type_link"] hassert(isOk, "NewUseLink(): name=%q, field `type_link` not found
%+v", id, elemBase.StrElem_) typeLink, isOk := _typeLink.(string) hassert(isOk, "NewUseLink(): name=%q, `type_link`(%+v) not string", id, _typeLink) hassert(typeLink != "", "NewUseLink(): name=%q, type_link=%q is empty", id, typeLink) sf := &UseLink{ ElemBase_: elemBase, CoordEnd_: coordEnd, Src_: src, Dst_: dst, TypeLink_: typeLink, } return sf } // Links -- ссылки актора func (sf *UseLink) Links() []alias.Id { return []alias.Id{sf.Src_, sf.Dst_} } // Check -- проверяет связи между объектами func (sf *UseLink) Check(mapDrawer map[alias.Id]types.IElemDrawer) string { if sf.Dst_ == sf.Src_ { return fmt.Sprintf("ВНИМАНИЕ! Источник и получатель совпадают\nsrc=%v, dst=%v\n", sf.Src_, sf.Dst_) } if msgErr := sf.checkSrc(mapDrawer); msgErr != "" { return "ОШИБКА при проверке связи источника\n" + msgErr } if msgErr := sf.checkDst(mapDrawer); msgErr != "" { return "ОШИБКА при проверке связи получателя\n" + msgErr } if sf.TypeLink_ == "" { // Проверка на правильность типа связи return "Пустой собственный тип связи\n" } return "" } // проверить связь получателя func (sf *UseLink) checkDst(mapDrawer map[alias.Id]types.IElemDrawer) string { if sf.Dst_ == "" { return "ОШИБКА получатель `dst` не задан" } dst, isOk := mapDrawer[sf.Dst_] // Вычислить, если такой получатель if !isOk { return "Отсутствует собственный получатель(dst)\n" } // Вычислить на допустимые типы для получателя switch dst.Type() { case cons.TypeUseActor: actor, isOk := dst.(types.IActor) if !isOk { return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n", dst.Id(), dst.Type()) } isOk = false for _, id := range actor.Links() { if id == sf.ElemBase_.Id_ { isOk = true break } } if !isOk { return fmt.Sprintf("Невзаимная ссылка\nid=%q,dst=(%q)", sf.ElemBase_.Id_, actor.Id()) } case cons.TypeUseLink: link, isOk := dst.(types.ILinker) if !isOk { return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n", dst.Id(), dst.Type()) } isOk = sf.ElemBase_.Id_ == link.DstId() || sf.ElemBase_.Id_ == link.SrcId() if !isOk { return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.ElemBase_.Id_, link.Id()) } case cons.TypeUseCase: useCase, isOk := dst.(types.IUseCase) if !isOk { return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nтип=%q\n", sf.ElemBase_.Id_, dst.Id(), dst.Type()) } isOk = false for _, id := range useCase.Links() { if id == sf.ElemBase_.Id_ { isOk = true break } } if !isOk { return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.ElemBase_.Id_, useCase.Id()) } default: // Недопустимый источник return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nid=%q\n", sf.ElemBase_.Id_, dst.Type(), dst.Id()) } return "" } // Проверяет связь источника func (sf *UseLink) checkSrc(mapDrawer map[alias.Id]types.IElemDrawer) string { if sf.Src_ == "" { return "ВНИМАНИЕ! Источник связи не задан(src)\n" } src, isOk := mapDrawer[sf.Src_] if !isOk { return "Отсутствует источник(src)\n" } switch src.Type() { case cons.TypeUseActor: isOk = false actor := types.IActor(src) for _, id := range actor.Links() { // Проверка на взаимность if id == sf.ElemBase_.Id_ { isOk = true break } } if !isOk { return fmt.Sprintf("Невзаимная ссылка с актором %q\n", actor.Id()) } case cons.TypeUseLink: link, isOk := src.(types.ILinker) if !isOk { return fmt.Sprintf("Несоответствие типа источника(%q)\nтип='useLink'\n", src.Id()) } isOk = sf.ElemBase_.Id_ == link.DstId() || sf.ElemBase_.Id_ == link.SrcId() if !isOk { return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.ElemBase_.Id_, link.Id()) } case cons.TypeUseCase: useCase, isOk := src.(types.IUseCase) if !isOk { return fmt.Sprintf("id=%q, Тип источника(%q) не совпадает с фактическим\nтип='useCase'\n", sf.ElemBase_.Id_, src.Id()) } isOk = false for _, id := range useCase.Links() { // Проверка на взаимность if id == sf.ElemBase_.Id_ { isOk = true break } } if !isOk { return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.ElemBase_.Id_, useCase.Id()) } default: // Неизвестный источник return fmt.Sprintf("id=%q, неизвестный тип источника(%q)
id=%q\n", sf.ElemBase_.Id_, src.Type(), src.Id()) } return "" } // SrcId -- возвращает источник связи func (sf *UseLink) SrcId() alias.Id { return sf.Src_ } // DstId -- возвращает получателя связи func (sf *UseLink) DstId() alias.Id { return sf.Dst_ }