From d0f63fda56e88a855784e1e8a1d5db522147b2ec Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Wed, 28 Sep 2022 16:13:20 +0200 Subject: [PATCH] add functionalities to the expression predicate evaluations --- pkg/goutils/goutils.go | 36 +++++++++++++++++++++++++++++++----- pkg/obiseq/predicate.go | 33 +++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/pkg/goutils/goutils.go b/pkg/goutils/goutils.go index f4eeaab..2c4e181 100644 --- a/pkg/goutils/goutils.go +++ b/pkg/goutils/goutils.go @@ -7,6 +7,7 @@ import ( "encoding/json" "io" "os" + "reflect" "sync" ) @@ -197,9 +198,34 @@ func AtomicCounter(initial ...int) func() int { // characters, json.Marshal should not be used. Playground of Go breaking a // title: https://play.golang.org/p/o2hiX0c62oN func JsonMarshal(i interface{}) ([]byte, error) { - buffer := &bytes.Buffer{} - encoder := json.NewEncoder(buffer) - encoder.SetEscapeHTML(false) - err := encoder.Encode(i) - return bytes.TrimRight(buffer.Bytes(), "\n"), err + buffer := &bytes.Buffer{} + encoder := json.NewEncoder(buffer) + encoder.SetEscapeHTML(false) + err := encoder.Encode(i) + return bytes.TrimRight(buffer.Bytes(), "\n"), err } + +func IsAMap(value interface{}) bool { + return reflect.TypeOf(value).Kind() == reflect.Map +} + +func IsAnArray(value interface{}) bool { + return reflect.TypeOf(value).Kind() == reflect.Array +} + +func IsASlice(value interface{}) bool { + return reflect.TypeOf(value).Kind() == reflect.Slice +} + +func HasLength(value interface{}) bool { + return IsAMap(value) || IsAnArray(value) || IsASlice(value) +} +func Length(value interface{}) int { + l := 1 + if HasLength(value) { + vc := reflect.ValueOf(value) + l = vc.Len() + } + + return l +} \ No newline at end of file diff --git a/pkg/obiseq/predicate.go b/pkg/obiseq/predicate.go index fc2adce..7832c4d 100644 --- a/pkg/obiseq/predicate.go +++ b/pkg/obiseq/predicate.go @@ -5,6 +5,7 @@ import ( "fmt" "regexp" + "git.metabarcoding.org/lecasofts/go/obitools/pkg/goutils" log "github.com/sirupsen/logrus" "github.com/PaesslerAG/gval" @@ -20,7 +21,11 @@ func (predicate1 SequencePredicate) And(predicate2 SequencePredicate) SequencePr return predicate1 default: return func(sequence *BioSequence) bool { - return predicate1(sequence) && predicate2(sequence) + if !predicate1(sequence) { + return false + } + + return predicate2(sequence) } } } @@ -33,7 +38,10 @@ func (predicate1 SequencePredicate) Or(predicate2 SequencePredicate) SequencePre return predicate1 default: return func(sequence *BioSequence) bool { - return predicate1(sequence) || predicate2(sequence) + if predicate1(sequence) { + return true + } + return predicate2(sequence) } } } @@ -195,8 +203,17 @@ func IsIdIn(ids ...string) SequencePredicate { func ExpressionPredicat(expression string) SequencePredicate { - exp, err := gval.Full().NewEvaluable(expression) - + lang := gval.NewLanguage( + gval.Full(), + gval.Function("len", func(args ...interface{}) (interface{}, error) { + length := goutils.Length(args[0]) + return (float64)(length), nil + }), + gval.Function("ismap", func(args ...interface{}) (interface{}, error) { + ismap := goutils.IsAMap(args[0]) + return ismap, nil + })) + exp, err := lang.NewEvaluable(expression) if err != nil { log.Fatalf("Error in the expression : %s", expression) } @@ -204,10 +221,10 @@ func ExpressionPredicat(expression string) SequencePredicate { f := func(sequence *BioSequence) bool { value, err := exp.EvalBool(context.Background(), map[string]interface{}{ - "annot": sequence.Annotations(), - "count": sequence.Count(), - "length": sequence.Length(), - "sequence": sequence, + "annot": sequence.Annotations(), + "count": sequence.Count(), + "seqlength": sequence.Length(), + "sequence": sequence, }, )