s0rg/decompose

View on GitHub
internal/structurizr/system.go

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
package srtructurizr

import (
    "io"
    "slices"
)

type System struct {
    containers    map[string]*Container
    relationships map[string]map[string]*Relation
    ID            string
    Name          string
    Description   string
    Tags          []string
    order         []string
}

func NewSystem(name string) *System {
    return &System{
        ID:            SafeID(name),
        Name:          name,
        containers:    make(map[string]*Container),
        relationships: make(map[string]map[string]*Relation),
    }
}

func (s *System) AddContainer(id, name string) (c *Container, ok bool) {
    id = SafeID(id)

    if _, ok = s.containers[id]; ok {
        return nil, false
    }

    c = &Container{
        ID:   id,
        Name: name,
    }

    s.containers[id] = c
    s.order = append(s.order, id)
    slices.Sort(s.order)

    return c, true
}

func (s *System) findRelation(src, dst string) (rv *Relation, found bool) {
    src, dst = SafeID(src), SafeID(dst)

    if dest, ok := s.relationships[src]; ok {
        if rel, ok := dest[dst]; ok {
            return rel, true
        }
    }

    if dest, ok := s.relationships[dst]; ok {
        if rel, ok := dest[src]; ok {
            return rel, true
        }
    }

    return nil, false
}

func (s *System) AddRelation(srcID, dstID, srcName, dstName string) (rv *Relation, ok bool) {
    src, ok := s.containers[SafeID(srcID)]
    if !ok {
        return nil, false
    }

    dst, ok := s.containers[SafeID(dstID)]
    if !ok {
        return nil, false
    }

    if rv, ok = s.findRelation(src.ID, dst.ID); ok {
        return rv, true
    }

    srcID, dstID = SafeID(src.ID), SafeID(dst.ID)

    dest, ok := s.relationships[srcID]
    if !ok {
        dest = make(map[string]*Relation)
    }

    rv, ok = dest[dstID]
    if !ok {
        rv = &Relation{
            Src: srcName,
            Dst: dstName,
        }
    }

    dest[dstID] = rv

    s.relationships[srcID] = dest

    return rv, true
}

func (s *System) WriteContainers(w io.Writer, level int) {
    putCommon(w, level, s.Description, "", s.Tags)

    next := level + 1

    for _, cID := range s.order {
        cont := s.containers[cID]

        putBlock(w, next, blockContainer, cont.ID, cont.Name)
        cont.Write(w, next+1)
        putEnd(w, next)
    }
}

func (s *System) WriteViews(w io.Writer, level int) {
    next := level + 1

    for _, cID := range s.order {
        cont := s.containers[cID]

        putView(w, level, blockComponent, cont.ID)

        putRaw(w, next, "include *")
        putRaw(w, next, "autoLayout")

        putEnd(w, level)
    }
}

func (s *System) WriteRelations(w io.Writer, level int) {
    for srcID, dest := range s.relationships {
        for dstID, rel := range dest {
            putRelation(w, level, srcID, dstID, rel.Tags)
            putEnd(w, level)
        }
    }
}