Skip to content
Snippets Groups Projects
Select Git revision
  • e8e363c0b6c1c37b7283ca4da1097030e020428b
  • master default protected
  • feature/PRXS-3383-CollectionsSort
  • refactor/PRXS-3053-Files
  • feature/PRXS-3143-3235-ReferenceOptions
  • feature/PRXS-3421-ImplementNewRefAPI
  • feature/PRXS-3143-LimitReferenceFields
  • feature/PRXS-3234-FeaturePruneIdents
  • feature/3149-LocaleCodeAsID-Feature
  • PRXS-3421-RecursiveReferences
  • feature/3109-SerializeFeature
  • release/0.33
  • feature/3109-RecoverySchema
  • feature/3109-feature
  • fix/PRXS-3369-ValidateFields
  • refactor/PRXS-3306-MovePkgGroup1
  • refactor/6-pkg-refactor-expr
  • fix/PRXS-3360-TemplateBuilderPatch
  • feature/3293-MongoV2
  • feature/3272-GoVersionUp
  • feature/PRXS-3218-HideTemplateActions
  • v0.33.1
  • v0.32.0
  • v0.31.1
  • v0.31.0
  • v0.30.0
  • v0.29.0
  • v0.28.0
  • v0.27.0-alpha.1+16
  • v0.27.0-alpha.1+15
  • v0.27.0-alpha.1+14
  • v0.27.0-alpha.1+13
  • v0.27.0-alpha.1+12
  • v0.27.0-alpha.1+11
  • v0.27.0-alpha.1+10
  • v0.27.0-alpha.1+9
  • v0.27.0-alpha.1+8
  • v0.27.0-alpha.1+7
  • v0.27.0-alpha.1+6
  • v0.27.0-alpha.1+5
  • v0.27.0-alpha.1+4
41 results

caching_middleware_test.go

Blame
  • options.go 3.25 KiB
    package field
    
    import (
    	"encoding/json"
    	"errors"
    	"fmt"
    	"reflect"
    	"sync"
    )
    
    type Option interface {
    	Transform(f *Field, v interface{}) (interface{}, error)
    }
    
    type PriorityOption interface {
    	GetPriority() int
    }
    
    type NamedOption interface {
    	GetName() string
    }
    
    type OptionValidator interface {
    	ValidateOption() error
    }
    
    //type jsonTransform struct {
    //	Name    string          `json:"name"`
    //	Options json.RawMessage `json:"options,omitempty"`
    //}
    //
    //func (t *Option) MarshalJSON() ([]byte, error) {
    //	b, err := json.Marshal(t.Transformation)
    //	if err != nil {
    //		return nil, err
    //	}
    //
    //	j := jsonTransform{Name: GetOptionName(t.Transformation), Options: b}
    //
    //	return json.Marshal(&j)
    //}
    //
    //func (t *Option) UnmarshalJSON(b []byte) error {
    //	var j jsonTransform
    //	if err := json.Unmarshal(b, &j); err != nil {
    //		return err
    //	}
    //
    //	i, ok := nameToOption.Load(j.Name)
    //	if !ok {
    //		return fmt.Errorf("unknown transformer name \"%s\"", j.Name)
    //	}
    //	typ := i.(reflect.Type)
    //	val := reflect.New(typ)
    //	v := val.Interface()
    //
    //	if len(j.Options) > 0 {
    //		if err := json.Unmarshal(j.Options, v); err != nil {
    //			return err
    //		}
    //	}
    //
    //	tr, _ := v.(Transformation)
    //	*t = Option{Transformation: tr}
    //	return nil
    //}
    
    var (
    	nameToOption sync.Map
    	optionToName sync.Map
    )
    
    func GetOptionName(o interface{}) string {
    	typ := reflect.TypeOf(o)
    	if typ.Kind() == reflect.Ptr {
    		typ = typ.Elem()
    	}
    	if val, ok := optionToName.Load(typ); ok {
    		v := val.(string)
    		return v
    	}
    	return ""
    }
    
    func RegisterOption(o interface{}) {
    	var name string
    	typ := reflect.TypeOf(o)
    	if typ.Kind() == reflect.Ptr {
    		typ = typ.Elem()
    	}
    
    	if namer, ok := o.(NamedOption); ok {
    		name = namer.GetName()
    	} else {
    		name = typ.Name()
    	}
    
    	nameToOption.Store(name, typ)
    	optionToName.Store(typ, name)
    }
    
    type Options map[string]interface{}
    
    func (options *Options) Add(opts ...interface{}) {
    	if len(opts) == 0 {
    		return
    	}
    	if *options == nil {
    		*options = make(Options)
    	}
    	for _, o := range opts {
    		name := GetOptionName(o)
    		(*options)[name] = o
    	}
    }
    
    //func (options Options) MarshalJSON() ([]byte, error) {
    //	m := make(map[string]json.RawMessage)
    //
    //	for k,v := range options {
    //		name := GetOptionName(t)
    //		b, err := json.Marshal(t)
    //		if err != nil {
    //			return nil, err
    //		}
    //		m[name] = b
    //	}
    //	return json.Marshal(&m)
    //}
    
    func (options *Options) UnmarshalJSON(b []byte) error {
    	m := make(map[string]json.RawMessage)
    	*options = make(Options)
    	if err := json.Unmarshal(b, &m); err != nil {
    		return err
    	}
    
    	for name, opts := range m {
    		i, ok := nameToOption.Load(name)
    		if !ok {
    			return fmt.Errorf("unknown option name \"%s\"", name)
    		}
    		typ := i.(reflect.Type)
    		val := reflect.New(typ)
    		v := val.Interface()
    		if len(opts) > 0 {
    			if err := json.Unmarshal(opts, v); err != nil {
    				return err
    			}
    		}
    		if validator, ok := v.(OptionValidator); ok {
    			err := validator.ValidateOption()
    			if errors.Is(err, ErrSkipOption) {
    				continue
    			}
    			if err != nil {
    				return err
    			}
    		}
    		options.Add(v)
    	}
    	return nil
    }
    
    func (options Options) Transform(field *Field, v interface{}) (interface{}, error) {
    	var err error
    	for _, t := range options {
    		o := t.(Option)
    		v, err = o.Transform(field, v)
    		if err != nil {
    			return nil, err
    		}
    	}
    	return v, nil
    }