use_link.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // package use_link -- связь между объектами
  2. package use_link
  3. import (
  4. "fmt"
  5. "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
  6. "gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
  7. "gitp78su.ipnodns.ru/svi/goarch/lev0/types"
  8. "gitp78su.ipnodns.ru/svi/goarch/lev1/coord"
  9. "gitp78su.ipnodns.ru/svi/goarch/pkg/elems/elem_base"
  10. "gitp78su.ipnodns.ru/svi/kern/v3"
  11. )
  12. // UseLink -- связь между объектами
  13. type UseLink struct {
  14. ElemBase_ *elem_base.ElemBase `yaml:"elem_base"`
  15. CoordEnd_ *coord.Coord `yaml:"coord1"` // Координаты второй точки
  16. Src_ alias.Id `yaml:"src"` // Источник координат
  17. Dst_ alias.Id `yaml:"dst"` // Получатель координат
  18. TypeLink_ string `yaml:"typeLink"` // Тип связи
  19. }
  20. var (
  21. hassert = kern.GetFnHassert()
  22. )
  23. // NewUseLink -- возвращает новую связь
  24. func NewUseLink(elemBase *elem_base.ElemBase, coordEnd *coord.Coord) *UseLink {
  25. hassert(elemBase != nil, "NewUseLink(): elemBase is nil")
  26. hassert(coordEnd != nil, "NewUseLink(): coordEnd is nil")
  27. id := elemBase.Id_
  28. _src := elemBase.Elem_["src"]
  29. src0, isOk := _src.(string)
  30. hassert(isOk, "NewUseLink(): id=%q, field `src` not string, type=%T, value=%v", id, _src, elemBase.StrElem_)
  31. src := alias.Id(src0)
  32. hassert(src != "", "NewUseLink(): id=%q, `src` is empty", id)
  33. _dst := elemBase.Elem_["dst"]
  34. dst0, isOk := _dst.(string)
  35. hassert(isOk, "NewUseLink(): id=%q, field `dst` not string, type=%T, value=%+v<br>%+v", id, _dst, _dst, elemBase.StrElem_)
  36. dst := alias.Id(dst0)
  37. _typeLink, isOk := elemBase.Elem_["type_link"]
  38. hassert(isOk, "NewUseLink(): name=%q, field `type_link` not found<br>%+v", id, elemBase.StrElem_)
  39. typeLink, isOk := _typeLink.(string)
  40. hassert(isOk, "NewUseLink(): name=%q, `type_link`(%+v) not string", id, _typeLink)
  41. hassert(typeLink != "", "NewUseLink(): name=%q, type_link=%q is empty", id, typeLink)
  42. sf := &UseLink{
  43. ElemBase_: elemBase,
  44. CoordEnd_: coordEnd,
  45. Src_: src,
  46. Dst_: dst,
  47. TypeLink_: typeLink,
  48. }
  49. return sf
  50. }
  51. // Links -- ссылки актора
  52. func (sf *UseLink) Links() []alias.Id {
  53. return []alias.Id{sf.Src_, sf.Dst_}
  54. }
  55. // Check -- проверяет связи между объектами
  56. func (sf *UseLink) Check(mapDrawer map[alias.Id]types.IElemDrawer) string {
  57. if sf.Dst_ == sf.Src_ {
  58. return fmt.Sprintf("ВНИМАНИЕ! Источник и получатель совпадают\nsrc=%v, dst=%v\n", sf.Src_, sf.Dst_)
  59. }
  60. if msgErr := sf.checkSrc(mapDrawer); msgErr != "" {
  61. return "ОШИБКА при проверке связи источника\n" + msgErr
  62. }
  63. if msgErr := sf.checkDst(mapDrawer); msgErr != "" {
  64. return "ОШИБКА при проверке связи получателя\n" + msgErr
  65. }
  66. if sf.TypeLink_ == "" { // Проверка на правильность типа связи
  67. return "Пустой собственный тип связи\n"
  68. }
  69. return ""
  70. }
  71. // проверить связь получателя
  72. func (sf *UseLink) checkDst(mapDrawer map[alias.Id]types.IElemDrawer) string {
  73. if sf.Dst_ == "" {
  74. return "ОШИБКА получатель `dst` не задан"
  75. }
  76. dst, isOk := mapDrawer[sf.Dst_] // Вычислить, если такой получатель
  77. if !isOk {
  78. return "Отсутствует собственный получатель(dst)\n"
  79. }
  80. // Вычислить на допустимые типы для получателя
  81. switch dst.Type() {
  82. case cons.TypeUseActor:
  83. actor, isOk := dst.(types.IActor)
  84. if !isOk {
  85. return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n", dst.Id(), dst.Type())
  86. }
  87. isOk = false
  88. for _, id := range actor.Links() {
  89. if id == sf.ElemBase_.Id_ {
  90. isOk = true
  91. break
  92. }
  93. }
  94. if !isOk {
  95. return fmt.Sprintf("Невзаимная ссылка\nid=%q,dst=(%q)", sf.ElemBase_.Id_, actor.Id())
  96. }
  97. case cons.TypeUseLink:
  98. link, isOk := dst.(types.ILinker)
  99. if !isOk {
  100. return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n", dst.Id(), dst.Type())
  101. }
  102. isOk = sf.ElemBase_.Id_ == link.DstId() || sf.ElemBase_.Id_ == link.SrcId()
  103. if !isOk {
  104. return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.ElemBase_.Id_, link.Id())
  105. }
  106. case cons.TypeUseCase:
  107. useCase, isOk := dst.(types.IUseCase)
  108. if !isOk {
  109. return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nтип=%q\n", sf.ElemBase_.Id_, dst.Id(), dst.Type())
  110. }
  111. isOk = false
  112. for _, id := range useCase.Links() {
  113. if id == sf.ElemBase_.Id_ {
  114. isOk = true
  115. break
  116. }
  117. }
  118. if !isOk {
  119. return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.ElemBase_.Id_, useCase.Id())
  120. }
  121. default: // Недопустимый источник
  122. return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nid=%q\n", sf.ElemBase_.Id_, dst.Type(), dst.Id())
  123. }
  124. return ""
  125. }
  126. // Проверяет связь источника
  127. func (sf *UseLink) checkSrc(mapDrawer map[alias.Id]types.IElemDrawer) string {
  128. if sf.Src_ == "" {
  129. return "ВНИМАНИЕ! Источник связи не задан(src)\n"
  130. }
  131. src, isOk := mapDrawer[sf.Src_]
  132. if !isOk {
  133. return "Отсутствует источник(src)\n"
  134. }
  135. switch src.Type() {
  136. case cons.TypeUseActor:
  137. isOk = false
  138. actor := types.IActor(src)
  139. for _, id := range actor.Links() { // Проверка на взаимность
  140. if id == sf.ElemBase_.Id_ {
  141. isOk = true
  142. break
  143. }
  144. }
  145. if !isOk {
  146. return fmt.Sprintf("Невзаимная ссылка с актором %q\n", actor.Id())
  147. }
  148. case cons.TypeUseLink:
  149. link, isOk := src.(types.ILinker)
  150. if !isOk {
  151. return fmt.Sprintf("Несоответствие типа источника(%q)\nтип='useLink'\n", src.Id())
  152. }
  153. isOk = sf.ElemBase_.Id_ == link.DstId() || sf.ElemBase_.Id_ == link.SrcId()
  154. if !isOk {
  155. return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.ElemBase_.Id_, link.Id())
  156. }
  157. case cons.TypeUseCase:
  158. useCase, isOk := src.(types.IUseCase)
  159. if !isOk {
  160. return fmt.Sprintf("id=%q, Тип источника(%q) не совпадает с фактическим\nтип='useCase'\n", sf.ElemBase_.Id_, src.Id())
  161. }
  162. isOk = false
  163. for _, id := range useCase.Links() { // Проверка на взаимность
  164. if id == sf.ElemBase_.Id_ {
  165. isOk = true
  166. break
  167. }
  168. }
  169. if !isOk {
  170. return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.ElemBase_.Id_, useCase.Id())
  171. }
  172. default: // Неизвестный источник
  173. return fmt.Sprintf("id=%q, неизвестный тип источника(%q)<br>id=%q\n", sf.ElemBase_.Id_, src.Type(), src.Id())
  174. }
  175. return ""
  176. }
  177. // SrcId -- возвращает источник связи
  178. func (sf *UseLink) SrcId() alias.Id {
  179. return sf.Src_
  180. }
  181. // DstId -- возвращает получателя связи
  182. func (sf *UseLink) DstId() alias.Id {
  183. return sf.Dst_
  184. }