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) }