central-arch-spec-models/query/indexer.go
2025-12-23 17:27:44 +01:00

117 lines
2.7 KiB
Go

package query
import "fmt"
type IndexedElement struct {
Name string
DisplayName *string
ReferencedData any
Parent *IndexedContainer
Containers []*IndexedContainer
}
func (e *IndexedElement) Init() {
for _, container := range e.Containers {
container.Parent = e
container.Init()
}
}
func (e *IndexedElement) String() string {
if e.Parent == nil {
panic("IndexedElement has no parent!")
}
return fmt.Sprintf("%s:%s", e.Parent.Parent, e.Name)
}
func (e *IndexedElement) PrintableName() string {
var result = e.Name
if e.DisplayName != nil {
result = *e.DisplayName
}
return result
}
func (e *IndexedElement) Find(c *Container) QueryResult {
return findInContainers(c, e.Containers)
}
type IndexedContainer struct {
Name string
Parent *IndexedElement
Elements []*IndexedElement
}
func (c *IndexedContainer) Init() {
for _, element := range c.Elements {
element.Parent = c
element.Init()
}
}
func (c *IndexedContainer) String() string {
var parentStr = ""
if c.Parent != nil {
parentStr = c.Parent.String()
}
return fmt.Sprintf("%s%s", parentStr, c.Name)
}
func (c *IndexedContainer) PrintableName() string {
return c.Name
}
func (c *IndexedContainer) Find(e *Element) QueryResult {
for _, element := range c.Elements {
if e.Name == element.Name {
if e.NextContainer != nil {
// If the element is found but the query expression continues
// with a container query, delegate the search to the element
return element.Find(e.NextContainer)
} else {
// If not, return the found element
return QueryResult{element}
}
}
}
// Return an empty list if the element is not found
return make(QueryResult, 0)
}
// A query tree is a bipartite graph composed of containers and elements.
// Only elements can be queried.
type IndexedRoot struct {
Containers []*IndexedContainer
}
func (r *IndexedRoot) Find(q *Query) QueryResult {
return findInContainers(&q.Container, r.Containers)
}
func (r *IndexedRoot) FindByRef(ref Reference) (QueryResult, error) {
var query, err = ref.Parse()
if err != nil {
return nil, err
}
return r.Find(query), nil
}
func findInContainers(queried *Container, containers []*IndexedContainer) QueryResult {
for _, container := range containers {
if queried.Name == container.Name {
if queried.NextElement != nil {
// If the container is found but the query expression continues
// with an element query, delegate the search to the container
return container.Find(queried.NextElement)
} else {
// If not, return all the elements in the found container
return container.Elements
}
}
}
// Return an empty list if the container is not found
return make(QueryResult, 0)
}