Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
package odata
import (
"strings"
"github.com/CiscoM31/godata"
)
// GetExpandValues extracts the values of the $expand query parameter and
// returns them in a []string, rejecting any $expand value that consists of more
// than just a single path segment.
func GetExpandValues(req *godata.GoDataQuery) ([]string, error) {
if req == nil || req.Expand == nil {
return []string{}, nil
}
var expand []string
for _, item := range req.Expand.ExpandItems {
paths, err := collectExpandPaths(item, "")
if err != nil {
return nil, err
}
expand = append(expand, paths...)
}
return expand, nil
}
// collectExpandPaths recursively collects all valid expand paths from the given item.
func collectExpandPaths(item *godata.ExpandItem, prefix string) ([]string, error) {
if err := validateExpandItem(item); err != nil {
return nil, err
}
// Build the current path
currentPath := prefix
if len(item.Path) > 1 {
return nil, godata.NotImplementedError("multiple segments in $expand not supported")
}
if len(item.Path) == 1 {
if currentPath == "" {
currentPath = item.Path[0].Value
} else {
currentPath += "." + item.Path[0].Value
}
}
// Collect all paths, including nested ones
paths := []string{currentPath}
if item.Expand != nil {
for _, subItem := range item.Expand.ExpandItems {
subPaths, err := collectExpandPaths(subItem, currentPath)
if err != nil {
return nil, err
}
paths = append(paths, subPaths...)
}
}
return paths, nil
}
// validateExpandItem checks if an expand item contains unsupported options.
func validateExpandItem(item *godata.ExpandItem) error {
if item.Filter != nil || item.At != nil || item.Search != nil ||
item.OrderBy != nil || item.Skip != nil || item.Top != nil ||
item.Select != nil || item.Compute != nil || item.Levels != 0 {
return godata.NotImplementedError("options for $expand not supported")
}
return nil
}
// GetSelectValues extracts the values of the $select query parameter and
// returns them in a []string, rejects any $select value that consists of more
// than just a single path segment
func GetSelectValues(req *godata.GoDataQuery) ([]string, error) {
if req == nil || req.Select == nil {
return []string{}, nil
}
sel := make([]string, 0, len(req.Select.SelectItems))
for _, item := range req.Select.SelectItems {
if len(item.Segments) > 1 {
return []string{}, godata.NotImplementedError("multiple segments in $select not supported")
}
sel = append(sel, item.Segments[0].Value)
}
return sel, nil
}
// GetSearchValues extracts the value of the $search query parameter and returns
// it as a string. Rejects any search query that is more than just a simple string
func GetSearchValues(req *godata.GoDataQuery) (string, error) {
if req == nil || req.Search == nil {
return "", nil
}
// Only allow simple search queries for now
if len(req.Search.Tree.Children) != 0 {
return "", godata.NotImplementedError("complex search queries are not supported")
}
searchValue := strings.Trim(req.Search.Tree.Token.Value, "\"")
return searchValue, nil
}
@@ -0,0 +1,160 @@
package odata
import (
"testing"
"github.com/CiscoM31/godata"
"github.com/stretchr/testify/assert"
)
func TestGetExpandValues(t *testing.T) {
t.Run("NilRequest", func(t *testing.T) {
result, err := GetExpandValues(nil)
assert.NoError(t, err)
assert.Empty(t, result)
})
t.Run("EmptyExpand", func(t *testing.T) {
req := &godata.GoDataQuery{}
result, err := GetExpandValues(req)
assert.NoError(t, err)
assert.Empty(t, result)
})
t.Run("SinglePathSegment", func(t *testing.T) {
req := &godata.GoDataQuery{
Expand: &godata.GoDataExpandQuery{
ExpandItems: []*godata.ExpandItem{
{Path: []*godata.Token{{Value: "orders"}}},
},
},
}
result, err := GetExpandValues(req)
assert.NoError(t, err)
assert.Equal(t, []string{"orders"}, result)
})
t.Run("MultiplePathSegments", func(t *testing.T) {
req := &godata.GoDataQuery{
Expand: &godata.GoDataExpandQuery{
ExpandItems: []*godata.ExpandItem{
{Path: []*godata.Token{{Value: "orders"}, {Value: "details"}}},
},
},
}
result, err := GetExpandValues(req)
assert.Error(t, err)
assert.Empty(t, result)
})
t.Run("NestedExpand", func(t *testing.T) {
req := &godata.GoDataQuery{
Expand: &godata.GoDataExpandQuery{
ExpandItems: []*godata.ExpandItem{
{
Path: []*godata.Token{{Value: "items"}},
Expand: &godata.GoDataExpandQuery{
ExpandItems: []*godata.ExpandItem{
{
Path: []*godata.Token{{Value: "subitem"}},
Expand: &godata.GoDataExpandQuery{
ExpandItems: []*godata.ExpandItem{
{Path: []*godata.Token{{Value: "subsubitems"}}},
},
},
},
},
},
},
},
},
}
result, err := GetExpandValues(req)
assert.NoError(t, err)
assert.Subset(t, result, []string{"items", "items.subitem", "items.subitem.subsubitems"}, "must contain all levels of expansion")
})
}
func TestGetSelectValues(t *testing.T) {
t.Run("NilRequest", func(t *testing.T) {
result, err := GetSelectValues(nil)
assert.NoError(t, err)
assert.Empty(t, result)
})
t.Run("EmptySelect", func(t *testing.T) {
req := &godata.GoDataQuery{}
result, err := GetSelectValues(req)
assert.NoError(t, err)
assert.Empty(t, result)
})
t.Run("SinglePathSegment", func(t *testing.T) {
req := &godata.GoDataQuery{
Select: &godata.GoDataSelectQuery{
SelectItems: []*godata.SelectItem{
{Segments: []*godata.Token{{Value: "name"}}},
},
},
}
result, err := GetSelectValues(req)
assert.NoError(t, err)
assert.Equal(t, []string{"name"}, result)
})
t.Run("MultiplePathSegments", func(t *testing.T) {
req := &godata.GoDataQuery{
Select: &godata.GoDataSelectQuery{
SelectItems: []*godata.SelectItem{
{Segments: []*godata.Token{{Value: "name"}, {Value: "first"}}},
},
},
}
result, err := GetSelectValues(req)
assert.Error(t, err)
assert.Empty(t, result)
})
}
func TestGetSearchValues(t *testing.T) {
t.Run("NilRequest", func(t *testing.T) {
result, err := GetSearchValues(nil)
assert.NoError(t, err)
assert.Empty(t, result)
})
t.Run("EmptySearch", func(t *testing.T) {
req := &godata.GoDataQuery{}
result, err := GetSearchValues(req)
assert.NoError(t, err)
assert.Empty(t, result)
})
t.Run("SimpleSearch", func(t *testing.T) {
req := &godata.GoDataQuery{
Search: &godata.GoDataSearchQuery{
Tree: &godata.ParseNode{
Token: &godata.Token{Value: "test"},
},
},
}
result, err := GetSearchValues(req)
assert.NoError(t, err)
assert.Equal(t, "test", result)
})
t.Run("ComplexSearch", func(t *testing.T) {
req := &godata.GoDataQuery{
Search: &godata.GoDataSearchQuery{
Tree: &godata.ParseNode{
Children: []*godata.ParseNode{
{Token: &godata.Token{Value: "test"}},
},
},
},
}
result, err := GetSearchValues(req)
assert.Error(t, err)
assert.Empty(t, result)
})
}