dynamo-browse/internal/dynamo-browse/services/scriptmanager/resultsetproxy.go

230 lines
5.5 KiB
Go

package scriptmanager
import (
"context"
"github.com/cloudcmds/tamarin/arg"
"github.com/cloudcmds/tamarin/object"
"github.com/lmika/audax/internal/dynamo-browse/models"
"github.com/lmika/audax/internal/dynamo-browse/models/queryexpr"
"github.com/pkg/errors"
)
type resultSetProxy struct {
resultSet *models.ResultSet
}
func (r *resultSetProxy) Interface() interface{} {
return r.resultSet
}
func (r *resultSetProxy) IsTruthy() bool {
return true
}
func (r *resultSetProxy) Type() object.Type {
return "resultset"
}
func (r *resultSetProxy) Inspect() string {
return "resultset"
}
func (r *resultSetProxy) Equals(other object.Object) object.Object {
otherRS, isOtherRS := other.(*resultSetProxy)
if !isOtherRS {
return object.False
}
return object.NewBool(r.resultSet == otherRS.resultSet)
}
// GetItem implements the [key] operator for a container type.
func (r *resultSetProxy) GetItem(key object.Object) (object.Object, *object.Error) {
idx, err := object.AsInt(key)
if err != nil {
return nil, err
}
realIdx := int(idx)
if realIdx < 0 {
realIdx = len(r.resultSet.Items()) + realIdx
}
if realIdx < 0 || realIdx >= len(r.resultSet.Items()) {
return nil, object.NewError(errors.Errorf("index error: index out of range: %v", idx))
}
return newItemProxy(r, realIdx), nil
}
// GetSlice implements the [start:stop] operator for a container type.
func (r *resultSetProxy) GetSlice(s object.Slice) (object.Object, *object.Error) {
return nil, object.NewError(errors.New("TODO"))
}
// SetItem implements the [key] = value operator for a container type.
func (r *resultSetProxy) SetItem(key, value object.Object) *object.Error {
return object.NewError(errors.New("TODO"))
}
// DelItem implements the del [key] operator for a container type.
func (r *resultSetProxy) DelItem(key object.Object) *object.Error {
return object.NewError(errors.New("TODO"))
}
// Contains returns true if the given item is found in this container.
func (r *resultSetProxy) Contains(item object.Object) *object.Bool {
// TODO
return object.False
}
// Len returns the number of items in this container.
func (r *resultSetProxy) Len() *object.Int {
return object.NewInt(int64(len(r.resultSet.Items())))
}
// Iter returns an iterator for this container.
func (r *resultSetProxy) Iter() object.Iterator {
// TODO
return nil
}
func (r *resultSetProxy) GetAttr(name string) (object.Object, bool) {
switch name {
case "table":
return &tableProxy{table: r.resultSet.TableInfo}, true
case "length":
return object.NewInt(int64(len(r.resultSet.Items()))), true
}
return nil, false
}
type itemProxy struct {
resultSetProxy *resultSetProxy
itemIndex int
item models.Item
}
func newItemProxy(rs *resultSetProxy, itemIndex int) *itemProxy {
return &itemProxy{
resultSetProxy: rs,
itemIndex: itemIndex,
item: rs.resultSet.Items()[itemIndex],
}
}
func (i *itemProxy) Interface() interface{} {
return i.item
}
func (i *itemProxy) IsTruthy() bool {
return true
}
func (i *itemProxy) Type() object.Type {
return "item"
}
func (i *itemProxy) Inspect() string {
return "item"
}
func (i *itemProxy) Equals(other object.Object) object.Object {
// TODO
return object.False
}
func (i *itemProxy) GetAttr(name string) (object.Object, bool) {
// TODO: this should implement the container interface
switch name {
case "result_set":
return i.resultSetProxy, true
case "index":
return object.NewInt(int64(i.itemIndex)), true
case "attr":
return object.NewBuiltin("attr", i.value), true
case "set_attr":
return object.NewBuiltin("set_attr", i.setValue), true
case "delete_attr":
return object.NewBuiltin("delete_attr", i.deleteAttr), true
}
return nil, false
}
func (i *itemProxy) value(ctx context.Context, args ...object.Object) object.Object {
if objErr := arg.Require("item.attr", 1, args); objErr != nil {
return objErr
}
str, objErr := object.AsString(args[0])
if objErr != nil {
return objErr
}
modExpr, err := queryexpr.Parse(str)
if err != nil {
return object.Errorf("arg error: invalid path expression: %v", err)
}
av, err := modExpr.EvalItem(i.item)
if err != nil {
return object.NewError(errors.Errorf("arg error: path expression evaluate error: %v", err))
}
tVal, err := attributeValueToTamarin(av)
if err != nil {
return object.NewError(err)
}
return tVal
}
func (i *itemProxy) setValue(ctx context.Context, args ...object.Object) object.Object {
if objErr := arg.Require("item.set_attr", 2, args); objErr != nil {
return objErr
}
pathExpr, objErr := object.AsString(args[0])
if objErr != nil {
return objErr
}
path, err := queryexpr.Parse(pathExpr)
if err != nil {
return object.Errorf("arg error: invalid path expression: %v", err)
}
newValue, err := tamarinValueToAttributeValue(args[1])
if err != nil {
return object.NewError(err)
}
if err := path.SetEvalItem(i.item, newValue); err != nil {
return object.NewError(err)
}
i.resultSetProxy.resultSet.SetDirty(i.itemIndex, true)
return nil
}
func (i *itemProxy) deleteAttr(ctx context.Context, args ...object.Object) object.Object {
if objErr := arg.Require("item.delete_attr", 1, args); objErr != nil {
return objErr
}
str, objErr := object.AsString(args[0])
if objErr != nil {
return objErr
}
modExpr, err := queryexpr.Parse(str)
if err != nil {
return object.Errorf("arg error: invalid path expression: %v", err)
}
if err := modExpr.DeleteAttribute(i.item); err != nil {
return object.NewError(errors.Errorf("arg error: path expression evaluate error: %v", err))
}
i.resultSetProxy.resultSet.SetDirty(i.itemIndex, true)
return nil
}