elem_link.go 6.1 KB

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